Skip to main content

Copy Constructor

To understand the concept of copy constructor let us write a small program with a simple class A with two constructors.


#include<iostream>
using namespace std;
class A
{
   int num;
public:
   A();//default
   A(int m);//parameterized
   int getnum();
};
A::A():num(0)
{
   cout<<"Default constructor"<<endl;
}
A::A(int m):num(m)
{
   cout<<"Parameterized constructor"<<endl;
}
int A::getnum()
{
   return num;
}
int main()
{
    A obj1;
    A obj2(10);
    A obj3 = obj1;
    cout<<"That's all"<<endl;
}
  

What is the output of this program?

usha@dell:~/cppPrograms$ g++ copycons.cpp
usha@dell:~/cppPrograms$ ./a.out
Default constructor
Parameterized constructor
That's all

Now the question is why do we have a call to only 2 constructors when we have created 3 objects in the main()?

obj1 calls default constructor as it had no arguments. obj2 calls parameterized constructor. Which function is called when obj3 is created as a copy of obj1?

A special constructor called as copy constructor is called for obj3

But where is the constructor? We did not write one. 

Compiler provides a copy constructor for each class by default which makes an exact copy of an object.

Copy Constructor

A copy constructor is a special constructor which is called whenever an object is created as a copy of another.

e.g.
A obj2 = obj1;


Here obj2 is should be created as a copy of obj1.  Program calls copy constructor to create obj2.

Copy ctor is also called when an object is sent as a value parameter to a function or an object is returned from a function as a value
.

By default, compiler provides a copy constructor, which copies the objects bitwise (shallow copy). This ctor is sufficient in most cases unless your class uses dynamic memory.

You can write your own copy constructor as shown below. Copy constructor takes one reference parameter of the same class.


A::A(const A& ob1)
{
/**code **/
}

The single parameter to the copy constructor should be a reference to object of the same class.

Copy constructor is called when
  1. An object is initialized with another object of same class.
  2. An object is sent as a value parameter to a function.
  3. An object is returned from a function by value.
#include<iostream>
using std::cout; 
using std::endl;
class A
{
 int num; 
public:
 A(int m=0);
 A(const A& obj);
 int getnum() { return num;} 
};
A::A(int m):num(m)
{
 cout<<"Constructor";
}
A::A(const A& obj)
{
 num = obj.num;
 cout<<"Copy Constructor";
}
void printA(A obja)
{
 cout<<"Number is "<<obja.getnum(); 
}
int main()
{
 A obj1(10);
 cout<<"copy creation";
 A obj2(obj1);
 cout<<"Fn call with value parameter"; 
 printA(obj1);
}

Output
Constructorcopy creationCopy ConstructorFn call with value parameterCopy ConstructorNumber is 10

Creation of obj2 calls copy constructor. And printA() function takes value parameter. That also calls copy ctor. 

Shallow copy and deep copy

Copy constructor provided by compiler does shallow copy; all members of new object are copied from respective members of original object bit by bit.

If there are pointers in the object, the constructor just copies the pointer address to new object, instead of allocating new memory and copying the contents. Hence pointers of both original object and new object point to the same location.

If one of the objects is destroyed, then pointer of other object becomes dangling pointer and causes program to crash.
class A
{
 int *ptr;
 int size;
 public: 
 A(int n);
 ~A();
};
A::A(int n):size(n)
{ 
 ptr = new int[size];/*allocate memory */
 for(int i=0;i<size;i++)
 ptr[i] = 0;
}
A::~A()
{
 delete []ptr;
}
int main()
{
 A obj1(10);
 A obj2 = obj1;
}
 
The class A does not have a copy constructor. So compiler provides a copy ctor which does a shallow copy. This program crashes because both obj1 and obj2 have same pointer ptr. When obj2 is destroyed, the pointer is released. Now destructor call of obj1 tries to release this dangling pointer  and this crashes the program.

To avoid this problem,
 whenever a class has a member with dynamic memory, it must have a user defined copy constructor - which should perform a deep copy i.e. which should copy the content after allocating new memory for the pointer member.
class A
{
 int *ptr;
 int size;
 public:
 A(const A &obj1);
 A(int n);
 /* code*/
};
A::A(const A&obj1)/*copy constructor*/
{
 size = obj1.size;
 ptr = new int[size];/*allocate memory for deep copy*/
 for(int i=0;i<size;i++)/* copy contents*/
 ptr[i] = obj1.ptr[i];
}

In the example above, the  copy constructor takes care of memory allocation and then copying the elements. 

Note:
  1. If a class does not have dynamic allocation, then the compiler provided copy constructor is sufficient
  2. If a class has dynamically allocated members, then it must re-define all the 4 methods provided by the compiler viz. default constructor, copy constructor, assignment operator and destructor.

Comments

Popular posts from this blog

Find the error in C++ program

This C++ program is not compiling. What do you think is the error with the program? #include<iostream> using namespace std; int main() {    int arr[10];    arr={1,2,3,4,5,6,7,8};    cout<<"arr[0]="<<arr[0];    return 0; } Is the error due to Not using printf Initialising the array with only 8 elements instead of 10 Initialising array in the next statement instead of in definition. None of the above  Now if you like this question, there are plenty more questions like this and programs and notes in my app Simplified C++. Download the Simplif ied C++   by Hegdeapps now By the way the correct answer is (3)

Abstract class

 If we can not create any objects of a class, then it is called an abstract class. A class is made abstract by adding at least one pure virtual function to it. Pure virtual function A function is said to be a pure virtual function , if it has no definition but has only declaration. Pure virtual function is defined with the keyword virtual and followed by return type, function name and "=0". class Shape { public: virtual void printarea() =0 ; }; int main () { Shape obj1; //error } Here printarea() function of Shape class is a pure virtual function as it has no body. To make a function as pure virtual function, you should use =0 at the end of virtual function declaration Abstract class When a class has at least one pure virtual function, it is incomplete and no objects can be created from that class. Such a class is called an abstract class . In the earlier example class Shape is an abstract class, and objects can not be created from t...

Friends of C++

Friend function Remember that a member which is not public (Private and protected )  can not be accessed from outside the class.  Three are some situations where you may need to access these. Keyword friend  is used for this. A friend functions and classes can access all members of a class.  This concept is controversial. People say friend concept violates data encapsulation  A friend function is a non-member function but still can access all the members of a class including private members. Such a function is declared within class body with the prefix "friend" class Number { int num; public: Number( int m){ /*code*/ } friend void printNum(Number ob); /*friend function*/ }; void printNum (Number obj) { cout << obj.num << "endl" ; } printNum() is not member of class Number . But it can still access all members including private members, because it is a friend. Friend class An object of a friend c...