How does copy constructor execute?

282 Views Asked by At

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!

4

There are 4 best solutions below

0
463035818_is_not_an_ai On BEST ANSWER

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.

0
Gaurav Sehgal On

Consider Shallow copy to mere assignment. So,

Test t2 = t1; 

means

t2.a = t1.a

Since a is an int, If you modify a, from t1, it will not reflect in t2. So for int shallow copy is indeed deep copy.

Consider the case a was of type int*. Now t2.a and t1.a both point to same memory locations. So if you modify the value at memory location t1.a, the same would be reflected via t2.a since they are infact pointing to same location.

0
Michael Kenzel On

The implicitly-defined copy constructor of a class simply copies each member [class.copy.ctor]/14. Copying the members basically means that every member of the new object (the one being copied into) is initialized from the corresponding member of the object being copied in the same way as if you had written

T member(original.member);

where T is the type of the member and original is the object being copied. If member is of class type, this effectively boils down to invoking the copy constructor of T. However, your member is a plain int, which is not a class type. There is no copy constructor to call (int does not have a copy constructor); the int in the new object is simply initialized from the int of the original object, which boils down to copying the value of the original int into the new int

Your compiler does not distinguish between deep copy versus shallow copy, it doesn't even know what "deep copy" or "shallow copy" would be supposed to mean. There is no such thing as a deep copy or a shallow copy in C++ at the language level. These are simply terms that are commonly used by programmers to talk about different approaches for copying objects that logically (but not physically) contain other objects…

0
darune On

I read online that default copy constructor does "shallow copy"

This is not the right way of thinking of the copy constructor. The default copy constructor is just copying whatever members are in the type as if applying the copy constructor in turn on the members.

From reference:

If the implicitly-declared copy constructor is not deleted, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used. For union types, the implicitly-defined copy constructor copies the object representation (as by std::memmove). For non-union class types (class and struct), the constructor performs full member-wise copy of the object's bases and non-static members, in their initialization order, using direct initialization.

So it is more like a deep-copy actually than a shallow-copy.