Handy Andy wrote: |
---|
Using using namespace std; in a header file is a problem waiting to happen, but you will figure that one out the hard way. |
If you don't want to bother with std::, just declare
using namespace std
locally, within the scope you want it to apply. More about this here [1].
totoo wrote: |
---|
Also, how would I start with copy constructor and assignment? |
I'm also learning about copy constructor and copy assignments. They're deceptively simple.
You define a copy constructor by overloading your user class ctor to take a reference of itself. Usually, the reference is
const
because when you copy an object, you wouldn't normally change the copied object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class Queue {
int size;
std::vector<int> stuff;
Queue(int n) {...}
// Copy constructor
Queue(const Queue& queueThatsCopied)
: size(queueThatsCopied.size)
{
// In this context, `this` refers to the copy that needs to be initialized and queueThatsCopied refers to the object being copied (the right of the assignment).
this->stuff = queueThatsCopied.stuff; // Invoke std::vector<int>'s copy-constructor
// Do other stuff to initialize the copy
}
// Copy assignment
Queue& operator=(const Queue& rhs) {...}
// Move assignment
Queue& operator=(const Queue&& rhs) {...}
};
|
Copy constructors get called in contexts where your objects get copied (implicitly or explicitly) such as:
1. When you pass a parameter in by value (the variable in the calling scope gets copied to the parameter variable in the function scope).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
class Person
{
public:
Tea tea;
}
main()
{
Person drinker = Person("Alice");
MakeTea(drinker);
}
static void MakeTea(Person teaDrinker)
{
// Person class' copy constructor is invoked to obtain a copy of `drinker` which is then assigned to teaDrinker
teaDrinker.tea = Tea("Jasmine Tea"); // Calling scope does not receive this Tea
// Destructor for teaDrinker gets called.
}
|
2. When you return a variable with function scope by value (the variable in the function scope gets copied to a variable (or to an R-value) in the calling scope).
1 2 3 4 5 6 7 8 9 10 11 12 13
|
main()
{
Tea myTea = MakeTea(); // Returns L-value which is then assigned to myTea
CoolTeaByBlowing(MakeTea()); // Returns product as R-value which is then passed to CoolTeaByBlowing()
}
static Tea MakeTea()
{
Tea product = Tea.MakeUserTea();
return product; // Invokes Tea class' copy constructor
// product is copied to myTea
// Tea class' destructor is invoked for product
}
|
3. When you assign an object to another variable:
1 2 3
|
Foo f1("Foo1");
Foo f2 = f1; // Invokes Foo copy constructor (user-defined, if specified, otherwise default)
|
Yeah, I'm not here to provide a tutorial but that's what I've learned by writing some sample code.
Copy assignment is an operator overload that you define for a class that allows you to specify what happens when you assign one object to another:
1 2 3 4
|
Queue q1{...initialize}
Queue q2{...initialize}
q1 = q2; // Invokes copy assignment operator
Queue q3 = DoStuffThatReturnsAQueue(); // This method returns an R-Value, a Queue. The '=' invokes move assignment operator
|
There are two ways to define copy assignment and they're distinguished based on whether you copy-assign an L-Value or R-Value. The copy-assignment for an R-value is called
move assignment see [2, @10:53].
Copy assignments require you to know about L-Values and R-Values, see [2, @8:39-10:33, @10:45], [3].
[1]
https://www.youtube.com/watch?v=4NYC-VU-svE
[2]
https://www.youtube.com/watch?v=St0MNEU5b0o
[3]
https://www.youtube.com/watch?v=BvR1Pgzzr38