A copy constructor is a special constructor that creates a new object by copying an existing object of the same class. It is automatically invoked whenever a new object is initialized from another object of the same type.
- Invoked when a new object is created using an existing object.
- The compiler provides a default copy constructor if one is not defined.
Example: The following program demonstrates a 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 explicitly defined, the compiler-generated copy constructor performs a member-wise copy of a1 into a2.
Types of Copy Constructor
Copy constructors can be classified into different types based on how they are defined and used in a C++ program.
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.
#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
Explanation: 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.
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:
- obj is 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
A shallow copy copies data members directly from one object to another.

- Copies primitive data correctly.
- Copies pointer addresses instead of the data they point to.
- Multiple objects share the same memory.
- Can lead to dangling pointers or double deletion.
Deep Copy
A deep copy creates an independent copy of dynamically allocated resources.

- Allocates new memory for copied data.
- Each object owns its own copy of the resource.
- Prevents unintended side effects.
- Eliminates double deletion and dangling pointer issues.
Example: The following program 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.
MyClass obj2 = obj1;
- When an object is passed to a function by value.
void fun(MyClass obj);
- When an object is returned from a function by value.
MyClass fun()
{
MyClass obj;
return obj;
}
- When the compiler creates a temporary object.