Copy Constructor
The copy constructor is a constructor that creates an object by initializing it with an object of the same class which has been created previously. The copy constructor is used to −
- Initialize one object from another of the same type.
- Copy an object to pass it as an argument to a function.
- Copy an object to return it from a function.
If a copy constructor is not defined in a class, the compiler itself defines one.If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.
Syntax
The most common form of copy constructor is shown here −
classname(const classname &obj){// body of constructor}
Here, obj is a reference to an object that is being used to initialize another object.
Example of Copy Constructor
The following example demonstrates the use of the copy constructor:
#include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
ptr =newint;*ptr = len;}Line::Line(const Line &obj){
cout <<"Copy constructor allocating ptr."<< endl;
ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
Line line(10);display(line);return0;}
When the above code is compiled and executed, it produces the following result −
Normal constructor allocating ptr Copy constructor allocating ptr. Length of line : 10 Freeing memory! Freeing memory!
Copy Constructor to Create New Object
You can create a new object by using the existing object through the concept of a copy constructor.
In the following example, the copy constructor is used to create a new object as a copy of an existing object.
Example
Let us see the same example but with a small change to create another object using existing object of the same type −
#include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
ptr =newint;*ptr = len;}Line::Line(const Line &obj){
cout <<"Copy constructor allocating ptr."<< endl;
ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
Line line1(10);
Line line2 = line1;// This also calls copy constructordisplay(line1);display(line2);return0;}
When the above code is compiled and executed, it produces the following result −
Normal constructor allocating ptr Copy constructor allocating ptr. Copy constructor allocating ptr. Length of line : 10 Freeing memory! Copy constructor allocating ptr. Length of line : 10 Freeing memory! Freeing memory! Freeing memory!
Implicit vs. Explicit Copy Constructors
In C++, there are two types of Copy Constructors that’s Implicit and Explicit. Here we will discuss the difference between these two.
Implicit Copy Constructor
If the user doesn’t define their own copy constructor, then the compiler automatically provides an implicit copy constructor. It performs a shallow copy of the object, which means that it copies the values of each member of the object to the new object.
When is the Implicit Copy Constructor called?
- When a user passes an object by value to a function.
- When the user returns an object by value from a function.
- When the user initializes an object with another object of the same type (copy initialization).
Explicit (User-Defined) Copy Constructor
It is the user-defined constructor. This gives you access to customize the copy behavior like creating a deep copy instead of the default shallow copy.
Example
Here is the example for both explicit and implicit copy constructors in C++:
#include <iostream>usingnamespace std;classMyClass{private:int value;public:// ConstructorMyClass(int v):value(v){}// Explicit Copy ConstructorMyClass(const MyClass& other):value(other.value){
cout <<"Explicit Copy Constructor called"<< endl;}voiddisplay()const{ cout <<"Value: "<< value << endl;}};voidprocessValue(MyClass obj){// Implicit copy constructor will be called here
obj.display();}intmain(){
MyClass obj1(10);// Constructor called
MyClass obj2 = obj1;// Explicit copy constructor called
obj1.display();
obj2.display();processValue(obj1);// Implicit copy constructor calledreturn0;}
When the above code is compiled and executed, it produces the following result −
Explicit Copy Constructor called Value: 10 Value: 10 Explicit Copy Constructor called Value: 10
Rule of Three/Five
The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:
The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:
- Rule of Three:
- destructor (~ClassName()).
- And copy assignment operator (ClassName& operator=(const ClassName& other)), to ensure that memory is correctly managed.
- Rule of Five:
- move constructor (ClassName(ClassName&& other)).
- move assignment operator (ClassName& operator=(ClassName&& other))”.
These special member functions are necessary for the proper management of dynamic memory and other and other resources like file handling or network connections in a class.
Deep Copy vs. Shallow Copy
In C++, deep copy and shallow copy are different ways of copying objects and they are important when a class involves dynamic memory management.
1. Shallow Copy
It occurs when an object is copied in such a way that both original and copied objects share the same resources. This means that the copy constructor or copy assignment operator simply copies the values of data members (like pointers), without allocating new memory or making independent copies of the resources.
Example
#include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// ConstructorMyClass(int value){
data =newint(value);// Allocate memory}// Shallow Copy ConstructorMyClass(const MyClass& other){
data = other.data;// Copy pointer only}// Destructor~MyClass(){delete data;// Free memory}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
MyClass obj1(42);// Create an object
MyClass obj2 = obj1;// Use shallow copy constructor
obj1.showData();
obj2.showData();return0;}
When the above code is compiled and executed, it produces the following result −
Data: 42 Data: 42 free(): double free detected in tcache 2
2. Deep Copy
It occurs when an object is copied by allocating new memory for its own copy of the resources, making sure that the original and copied object is completely independent. Avoids double-free errors or dangling pointers.
Example
#include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// Constructor: Dynamically allocate memory // and initialize with valueMyClass(int value){ data =newint(value);}// Deep Copy Constructor// Allocates new memory and copies the valueMyClass(const MyClass& other){ data =newint(*other.data);}// Destructor to clean up memory~MyClass(){delete data;}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
MyClass obj1(42);// Create an object
MyClass obj2 = obj1;// Use deep copy constructor
obj1.showData();// Display data from obj1
obj2.showData();// Display data from obj2return0;}
When the above code is compiled and executed, it produces the following result −
Data: 42 Data: 42
Leave a Reply