1

During deep copy we are writing overloaded copy constructor and assignment operator. May i know why we have to write the overloaded assignment operator because we doing the same in overloaded copy constructor(except some check and return this).

Who is calling assignment operator

Sijith
  • 3,740
  • 17
  • 61
  • 101
  • You could implement deep copy through any function. The assignment constructor/operator does not need to make a deep copy. One example is a QString that does a shallow copy in it's assignment operator. I don't really understand what you mean by "Who is calling assignment operator" could you please provide code that demonstrates what you mean? – RedX Sep 13 '11 at 15:33

3 Answers3

5

Follow the Rule of Three:
If you need to write an copy constructor for your class, You also should write the Copy assignment operator and Destructor.

Copy Assignment operator and Copy Constructor both are called Copying functions. They basically help in getting a new copy of an object from an existing object. They both are separate entities invoked in different scenarios. So, just as in case of Copy constructor you ensure that you make deep copies of all pointer members and not just shallow copies, same would applies for copy assignment operator.

An Code Example:

class MyClass obj1, obj2;
class MyClass obj3(obj1);     //Calls Copy Constructor
obj1 = obj2;                  //Calls Copy Assignment Operator
Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 1
    Why is the destructor included in that list? – MGZero Sep 13 '11 at 15:34
  • @MGZero - What if the class has raw pointers as members pointing to memory locations acquired by **new** ? – Mahesh Sep 13 '11 at 15:35
  • 2
    @MGZero: Because chances are, if you need to do something special in the constructor, that means there are special resources being used that have to be disposed of correctly. – C. K. Young Sep 13 '11 at 15:35
2

The assignment operator is used if you do this:

MyType my1, my2;
my1 = my2;  // same as: my1.operator=(my2);
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • I'm pretty sure I've seen MSVC cheat and use the copy constructor in cases like these. I don't know if it's allowed to though. – Mooing Duck Sep 13 '11 at 16:13
  • @Mooing: I don't think it can, but if you do find it doing so, do post it as an code example Q here, I would be very interested to see that scenario. – Alok Save Sep 13 '11 at 16:24
  • @Als: I'll dig around in my experiments folders, but it seems unlikely that I can find it, or that I left it that way. More likely I called some other function between (.size() or something) to force it to use assignment. – Mooing Duck Sep 13 '11 at 16:32
  • I read (heard?) somewhere that `Type my1 = my2` is optimized in all cases to `Type my1(my2)`. – jwernerny Sep 13 '11 at 16:53
  • @jwernerny: This behaviour is no optimization, but actually required by the standard. –  Sep 13 '11 at 17:28
  • 1
    @jwernerny: `Type my1 = my2` is **Copy Initialization** and `Type my1(my2)` is **Direct Initialization** both actually result in call to a **Copy Constructor**, that is the Standard Behavior, no Optimization Involved at all. – Alok Save Sep 13 '11 at 18:11
0

The copy constructor and the assignment operator usually have very similar code, but if done properly (initializer lists) should be coded differently, used differently, and perform differently.

The copy constructor should use initializer lists. This is used for creating a new vector object that is the same as one already existing.

vector::vector(const vector& b) 
    :size(b.size),
    capacity(b.capacity),
    data(new TYPE[size]) 
{
    //there should be minimal code here
    //I'm skipping copying the data, because doing it right
    //is hard and beside the point
} 

vector seven;
seven.push_back(7);
vector seven_copy(seven); //make a new one, same as old

The assignment operator is probably exactly what you have. This is used to reassign an already existing vector object to be the same as one already existing

vector& vector::operator=(const vector& b) 
{
    //carefully written so self assignment doesn't crash.  
    TYPE* temp = new TYPE[b.size];
    //I'm skipping copying the data, because doing it right
    //is hard and beside the point
    delete [] data;
    //all exceptions that can be thrown, have, so it's safe to modify members now
    data = temp;
    size = b.size;
    capacity = b.capacity;
    return *this;
}

vector nine;
nine.push_back(9);
nine = seven;  //make an old one the same as another old

It should be noted that the move constructor and move assignment may look vaguely similar, but should probably be different as well.

vector::vector(vector&& b) 
    :size(b.size)
    capacity(b.capacity)
    data(b.data) //different!
{
    b.data = nullptr; 
}
vector& operator=(vector&& b)
{
     //since b.data is tied to b.size and b.capacity, it's safest to just swap
     //so if someone calls b.push_back() after, it's all still safe.
     std::swap(size, b.size);
     std::swap(capacity, b.capacity);
     std::data(data, b.data);
     return *this;
}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • The copy constructor should also check for self-assignment (`my1 = my1`) before doing anything. – jwernerny Sep 13 '11 at 16:54
  • No, it shouldn't check for it, it should be written so that it doesn't break if it is self assignment (like in http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom/3279550#3279550 ). In most cases, self assignment doesn't occurs often enough that you would need to try to optimize for it by un-optimizing the general case. – alexisdm Sep 13 '11 at 18:20
  • Sorry I wasn't clear enough: you can't remove the check for self assignment AND not fix the code to allow it. You have to copy, swap and then delete. If you delete before the copy, self assignment doesn't work. – alexisdm Sep 13 '11 at 18:49
  • technically, the bug then is the missing copy. I'll make that more obvious. – Mooing Duck Sep 13 '11 at 18:57