blog
blog copied to clipboard
C++ Copy Constructors
Concept: A copy constructor is a special constructor that is called whenever a new object is created and initialized with another object's data.
-
Special constructor used when a newly created object is initialized to the data of another object of same class:
Rectangel r2 = r1;
-
Default copy constructor copies field-to-field, using memberwise assignment.
(Memberwise assignment: use
=
to assign one object to another, or to initialize an object with an object's data, e.g.,instance2 = instance1;
)In C++, when you do not provide a copy constructor for your class, the compiler generates one for you.
SampleClass obj1(10, 20); // This calls the default copy constructor. // This operation is essentially a shallow copy (copy the address of the object). SampleClass obj2 = obj1;
A copy constructor is called when:
- An object is initialized from an object of the same class.
- An object is passed by value to a function.
- An object is returned using a
return
statement from a function.
1. Copy Constructor Example
A copy constructor is a member function that initializes an object using another object of the same class. It is used to perform a deep copy or sometimes a shallow copy of objects.
class SimpleClass {
private:
int num;
public:
// Default constructor
// SimpleClass() : num(0) {} // explicitly initialize num to 0
SimpleClass() {}
// Parameterized constructor
SimpleClass(int n) {
num = n;
}
// Copy constructor
// `const`: cannot modify the object obj inside the copy constructor.
// `&`: pass by reference rather than by value (make a copy).
// If pass it by value, cannot access the original object's private members.
SimpleClass(const SimpleClass &obj) {
num = obj.num;
}
void showNum() const {
std::cout << "Number: " << num << std::endl;
}
};
2. Deep Copy vs Shallow Copy
Since the default copy constructor is essentially a shallow copy (copy the address of the object). We need to define a copy constructor with objects containing dynamic memory.
// Deep Copy with Dynamic Memory Allocation
class DeepCopyClass {
private:
int *numPtr;
public:
// Default constructor
DeepCopyClass() {
numPtr = new int;
*numPtr = 0;
}
// Parameterized constructor
DeepCopyClass(int n) {
numPtr = new int;
*numPtr = n;
}
// Copy constructor for deep copy
// deep copy: copy the value of the object, not the address
// shallow copy: copy the address of the object
DeepCopyClass(const DeepCopyClass &obj) {
numPtr = new int; // allocate memory for the new object
*numPtr = *(obj.numPtr); // copy the value of the object
}
~DeepCopyClass() {
delete numPtr;
}
void showNum() const {
std::cout << "Number: " << *numPtr << std::endl;
}
};
// Shallow Copy (not recommended for dynamic memory)
class ShallowCopyClass {
private:
int *numPtr;
public:
// Default constructor
ShallowCopyClass() {
numPtr = new int;
*numPtr = 0;
}
// Parameterized constructor
ShallowCopyClass(int n) {
numPtr = new int;
*numPtr = n;
}
// Copy constructor for shallow copy
ShallowCopyClass(const ShallowCopyClass &obj) {
numPtr = obj.numPtr; // copy the address of the object
}
~ShallowCopyClass() {
delete numPtr;
}
void showNum() const {
std::cout << "Number: " << *numPtr << std::endl;
}
};