Copy Constructor in C++

Copy constructor is a constructor function with the same name as the class used to make copy of objects.

There are 3 important places where a copy constructor is called -

1)When an object is created from another object of the same type
2)When an object is passed by value as a parameter to a function
2)When an object is returned from a function

If a copy constructor is not defined in a class, the compiler itself defines one. This will ensure a shallow copy. If the class does not have pointer variables with dynamically allocated memory, then one need not worry about defining a copy constructor. It can be left to the compiler's discretion.
But if the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor. 

For ex:

                    class A //Without copy constructor
                    {
                         private:
                                   int x;
                         public:
                                   A() 
                                   {
                                          A = 10;
                                   }
                                   ~A() 
                                   {
                                   }
                    }
                   class B //With copy constructor
                    {
                        private:
                                  char *name;
                        public:
                                   B()
                                   {
                                         name = new char[20];
                                   }
                                   ~B()
                                   {
                                         delete name[];
                                   }
                                 //Copy constructor
                                  B(const B &b)
                                  {
                                         name = new char[20];
                                         strcpy(name, b.name);
                                   }
                     };

Let us Imagine if we don't have a copy constructor for the class B. At the first place, if an object is created from some existing object, we cannot be sure that the memory is allocated. Also, if the memory is deleted in destructor, the delete operator might be called twice for the same memory location. 

This is a major risk. One thing is, if the class is not so complex this will come to the fore during development itself. But if the class is very complicated, then these kind of errors will be difficult to track.
We all know that compiler will generate default constructor, destructor, copy constructor and copy assignment = operator by default if we dont define in our class definitions. 
Assume that, there is a scenario where we should not allow copy constructor and copy assignment operator in the program. 
Lets take some example, 
class A {/*...*/}; 
int main() 

        A a; /* default constructor */ 
        A b(a); /* copy constructor.. We should not allow this */ 
        b = a; /* copy assignment operator.. we should not allow this */ 

How do you achieve this? 

You can acheive this by making your copy constructor and assignment operator private.
here is your modified code 

class A 
{/*... 
      private : 
                 A(const A& ) 
                 { 
                 } 
                 A& operator=(const A ) 
                 { 
                 }
*/};
int main()
{
     A a; /* default constructor */
     A b(a); /* copy constructor.. We should not allow this */
     b = a; /* copy assignment operator.. we should not allow this */
}

now you will get compilation error saying copy constructor and assignment operator are private members.

You are right. You can have these in private and you don't have to implement that.
class A 

     private: 
               A(const A&);
               A& operator=(const A&);
     public: 

The difference between shallow and deep copying is only relevant for compound objects. (i.e objects that contain other objects, like lists/class instances or if objects has pointers to dynamically allocated memory). 


A shallow copy is bitwise copy of any object.
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Thus if the object has no pointers to dynamically allocated memory, a shallow copy is probably sufficient. Therefore the default copy constructor, default assignment operator, and default destructor should be sufficient.
If there are compound objects, then one has to define their own copy constructors, assignment operator and destructors for deep copy.

For Example:

// Shallow copy

Class Test
{       public:
              Test( int a, float b )
              {
                     i = a;
                     j = b;
               }
      private:
               int i;
               float j;
}
Test t1( 10, 20.0 );
Test t2(t1); // In this case, shallow copy is sufficient.


// Deep Copy

Class Test
{       public:
               Test( int a, char* s )
               {
                      i = a;
                      int len = strlen(s);
                      str = new char[len+1];
               }
      private:
                int i;
                char* str;
}
Test t1( 10, "Test" );
Test t2(t1); // In this case, deep copy is needed.

No comments:

Post a Comment