In C++, a copy constructor is a special member function that is used to create a new object as a copy of an existing object. It is called when a new object is initialized with an existing object of the same class. The copy constructor allows for the creation of a deep copy of the object, ensuring that all the member variables are correctly copied.
The syntax for a copy constructor is:
class ClassName { ClassName(const ClassName& obj) { // Copy constructor implementation } };
Here, ClassName
refers to the name of the class for which the copy constructor is being defined. The parameter const ClassName& obj
is a reference to the object that needs to be copied.
Let’s understand the concept of copy constructors with a few examples:
Example 1: Copying Primitive Data Types
#include class Number { private: int num; public: Number(int n) { num = n; } Number(const Number& obj) { num = obj.num; } int getNumber() { return num; } }; int main() { Number num1(10); Number num2 = num1; // Copy constructor called std::cout << "num1: " << num1.getNumber() << std::endl; std::cout << "num2: " << num2.getNumber() << std::endl; return 0; }
In this example, we have a class Number
with a member variable num
. The copy constructor is defined to copy the value of num
from one object to another. When we create num2
as a copy of num1
, the copy constructor is called, and num2
is initialized with the same value as num1
.
The output of this program will be:
num1: 10 num2: 10
Example 2: Copying Objects with Dynamic Memory Allocation
#include class String { private: char* str; public: String(const char* s) { int length = strlen(s); str = new char[length + 1]; strcpy(str, s); } String(const String& obj) { int length = strlen(obj.str); str = new char[length + 1]; strcpy(str, obj.str); } ~String() { delete[] str; } const char* getString() { return str; } }; int main() { String s1("Hello"); String s2 = s1; // Copy constructor called std::cout << "s1: " << s1.getString() << std::endl; std::cout << "s2: " << s2.getString() << std::endl; return 0; }
In this example, we have a class String
that manages a dynamically allocated character array. The copy constructor is defined to allocate a new memory block and copy the contents of the source object’s string. This ensures that each object has its own separate memory for the string.
The output of this program will be:
s1: Hello s2: Hello
It is important to note that when a class contains pointers or dynamically allocated memory, a copy constructor should be defined to perform a deep copy. Otherwise, both objects will end up pointing to the same memory location, leading to issues when one object is modified.
Example 3: Copy Constructor in Inheritance
#include class Base { protected: int value; public: Base(int v) { value = v; } Base(const Base& obj) { value = obj.value; } int getValue() { return value; } }; class Derived : public Base { public: Derived(int v) : Base(v) {} }; int main() { Derived d1(5); Derived d2 = d1; // Copy constructor called std::cout << "d1: " << d1.getValue() << std::endl; std::cout << "d2: " << d2.getValue() << std::endl; return 0; }
In this example, we have a base class Base
and a derived class Derived
. The copy constructor is defined in the base class, and it is called when creating a copy of a derived object. The derived object’s base part is copied using the copy constructor of the base class.
The output of this program will be:
d1: 5 d2: 5
By defining a copy constructor, you can control how objects are copied and ensure that the new object is a true copy of the original. This is especially important when dealing with dynamically allocated memory or when working with inheritance.
Remember to always define a copy constructor when necessary to avoid unexpected behavior and ensure the correct functioning of your C++ classes.