To understand the concept of copy constructor let us write a small program with a simple class A with two constructors.
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.
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.
You can write your own copy constructor as shown below. Copy constructor takes one reference parameter of the same class.
Output
Constructorcopy creationCopy ConstructorFn call with value parameterCopy ConstructorNumber is 10
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.
#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
- An object is initialized with another object of same class.
- An object is sent as a value parameter to a function.
- 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:
- If a class does not have dynamic allocation, then the compiler provided copy constructor is sufficient
- 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
Post a Comment