Search code examples
c++constructordefault-copy-constructor

How does copy constructor execute?


I'm trying to understand copy constructor in detail. While doing so, i made the following example,

#include<iostream>

class Test
{
private:
        int a;
public:
        /*
        Test(const Test &t)                          // User defined copy constructor
        {
            a = t.a;
        } */
        Test()
        {
                a = 120;
        }
        int display()
        {
                return a ;
        }
        void set(int var)
        {
                a = var;
        }
};

int main()
{
        Test t1;
        std::cout << "t1.a " << t1.display() << std::endl;
        Test t2 = t1;                                           //Default copy constructor is called
        std::cout << "T2.a " << t2.display() << std::endl;
        t2.set(99);                                             //Changing the value
        std::cout << "t1.a " << t1.display() << std::endl;
        std::cout << "T2.a " << t2.display() << std::endl;
        return 0;
}

I read online that default copy constructor does "shallow copy" So it means if obj1 = obj2, what ever change i do in obj1 or obj2 even after the assignment needs to be reflected on both the object as they point to same location. But in this example when i change the value in one object it is not getting reflected in the other. Same result is obtained when using user defined copy constructor.

Can some one clarify this topic, whether shallow copy is happening or not!

Thanks!


Solution

  • A shallow copy is not something special that you need to remember as rule. Instead it is just something that happens as a consequence of using a reference or pointer. COnsider this example:

    struct foo { 
         int* x;
    };
    
    int a = 4;
    foo f{&a};
    

    Here x points to a and if you copy f the new instances x will point to the same a. Thats a shallow copy. A deep copy would be to respect that not only x, but also what x points to, is an integral part of foo and needs to be copied as well. In general the compiler cannot decide what you want. Is x just a reference, or is what x refers to also part of foo? Hence what you get is the obvious: Only the members are copied not what they might refer to.

    Now, if you copy the foo and then modify the value x points to, then this will modify the same a. A shallow copy was made. To my experience the terms deep and shallow copy are rather adding confusion than clarity. What you get for free is all members get copied (whether is is a shallow or deep copy). Only if you need more (copy also the pointee), you need to worry about shallow vs deep copies.

    TL;DR: There is no deep/shallow copy in your example. For values this distinction does not make sense. Use a int* to see the effect.