A copy constructor is a special constructor that creates a new object by copying an existing object of the same class.
- Invoked when an object is initialized using another object of the same type.
- The compiler generates a default copy constructor if none is provided.
- The default copy constructor performs a shallow copy of data members.
- Classes that manage dynamic memory or other resources often require a custom copy constructor.
#include <iostream>
using namespace std;
// Demo class
class A {
public:
int x;
};
int main()
{
A a1;
a1.x = 10;
cout << "a1's x = " << a1.x << endl;
// Copy constructor called
A a2(a1);
cout << "a2's x = " << a2.x;
return 0;
}
Output
a1's x = 10 a2's x = 10
Explanation: The object a2 is created using a1. Since no copy constructor is defined, the compiler-generated copy constructor copies the value of x from a1 to a2.
Default Copy Constructor
If a class does not define a copy constructor, the compiler automatically generates one.
- Performs a member-wise copy of all data members.
- Suitable for classes containing primitive data types.
- Creates a shallow copy of pointers and references.
- May cause issues when objects manage dynamic resources.
In this example, a1 is created and its member x is set to 10. Then a2 is created using the copy constructor, so it becomes a copy of a1 with the same value of x.
#include <iostream>
using namespace std;
// Create a demo class
class A
{
public:
int x;
};
int main()
{
// Creating an a1 object
A a1;
a1.x = 10;
cout << "a1's x = " << a1.x << endl;
// Creating another object using a1
A a2(a1);
cout << "a2's x = " << a2.x;
return 0;
}
Output
a1's x = 10 a2's x = 10
User Defined Copy Constructor
A custom copy constructor allows programmers to define how objects should be copied.
Syntax
ClassName(const ClassName& obj){
// Copy data members
}
Where:
objis the source object being copied.- const prevents accidental modification of the source object.

#include <iostream>
using namespace std;
class A
{
public:
int x;
A(){};
// Copy Constructor definition
A(A &obj)
{
x = obj.x;
cout << "Copy constructor "
"called"
<< endl;
}
};
int main()
{
// Creating an object of class A
A obj1;
obj1.x = 10;
cout << "obj1's x = " << obj1.x << endl;
// Creating another object by copying already created object
A obj2(obj1);
cout << "obj2's x = " << obj2.x;
return 0;
}
Output
obj1's x = 10 Copy constructor called obj2's x = 10
Explanation: The user-defined copy constructor copies the value of x from obj1 to obj2 and displays a message when invoked.
Note: If we define a copy constructor, then implicit definition of the default constructor will not be provided by the compiler. So, we would have to manually define it too.
Need of User Defined Copy Constructor
The compiler-generated copy constructor performs a shallow copy, which may not be suitable for classes that manage resources.
- Copies pointer addresses instead of the actual data.
- Multiple objects may share the same resource.
- Can cause dangling pointers and double deletion errors.
- Required when working with dynamic memory, files, sockets, etc.
Shallow Copy
- Copies data members directly.
- Pointer members point to the same memory location.
- Changes in one object may affect the other.

Deep Copy
- Creates a separate copy of dynamically allocated resources.
- Each object manages its own memory.
- Prevents resource conflicts and unintended side effects.

The following example demonstrates a deep copy implementation.
#include <bits/stdc++.h>
using namespace std;
class String
{
private:
char *s;
int size;
public:
String(const char *str)
{
size = strlen(str);
s = new char[size + 1];
strcpy(s, str);
}
~String()
{
delete[] s;
}
String(const String &old_str)
{
size = old_str.size;
s = new char[size + 1];
strcpy(s, old_str.s);
}
void print()
{
cout << s << endl;
}
void change(const char *str)
{
delete[] s;
size = strlen(str);
s = new char[size + 1];
strcpy(s, str);
}
};
int main()
{
String str1("GeeksQuiz");
// Create str2 from str1
String str2 = str1;
str1.print();
str2.print();
// Update the str2 object
str2.change("GeeksforGeeks");
str1.print();
str2.print();
return 0;
}
Output
GeeksQuiz GeeksQuiz GeeksQuiz GeeksforGeeks
Explanation: The copy constructor allocates new memory and copies the string contents. Therefore, modifying str2 does not affect str1.
Note: Such classes also need the overloaded assignment operator. See this article for more info - C++ Assignment Operator Overloading
Effects of Removing the Copy Constructor
Removing the custom copy constructor from the previous example causes the compiler to perform a shallow copy.
- Both objects share the same memory.
- Changes to one object affect the other.
- Deleting one object may invalidate the other.
- Can lead to dangling pointers and double deletion.
Situations Where a Copy Constructor Is Invoked
A copy constructor may be called in the following cases:
- When an object is initialized using another object.
- When an object is passed to a function by value.
- When an object is returned from a function by value.
- When the compiler creates a temporary object.
Copy Elision
Copy elision is a compiler optimization that eliminates unnecessary object copies.
- Reduces memory usage.
- Improves program performance.
- Commonly performed through RVO and NRVO optimizations.
Copy Constructor vs Assignment Operator
Both the copy constructor and assignment operator are used to copy data from one object to another, but they are invoked in different situations.
- A copy constructor is called when a new object is created using an existing object.
- An assignment operator is called when data is assigned to an already existing object.
- A copy constructor initializes a new object, while the assignment operator updates an existing one.
Consider the following statements:
MyClass t1, t2;
MyClass t3 = t1; // (1)
t2 = t1; // (2)
Explanation: Statement (1) creates a new object t3 from t1, so the copy constructor is invoked. Statement (2) assigns the value of t1 to the already existing object t2, so the assignment operator is invoked.