Copy Constructors in C++

Every class has a copy constructor, which is used to copy objects.

Each class may define several overloaded constructors and one destructor. Additionally, every class has a copy constructor, which can be used to create an object initialized with the data of another object of the same class.

The signature of the copy constructor is

C1assName(const C1assName&)

For example, the copy constructor for the Circle class is

Circ1e(const Circ1e&)

A default copy constructor is provided for each class implicitly, if it is not defined explic­itly. The default copy constructor simply copies each data field in one object to its counterpart in the other object. Listing 11.17 demonstrates this.

Listing 11.17 CopyConstructorDemo.cpp

1 #include <iostream>
2
#include “CircleWithDestructor.h” // Defined in Listing 11.11
3 using namespace std;
4
5
int main()
6 {
7    Circle circle1(
5);
8    Circle circle2(circle1);
// Use copy constructor
9
10   cout <<
“After creating circle2 from circle1:” << endl;
11   cout <<
“\tcircle1.getRadius() returns ”
12     << circle1.getRadius() << endl;
13   cout <<
“\tcircle2.getRadius() returns ”
14     << circle2.getRadius() << endl;
15
16   circle1.setRadius(
10.5);
17   circle2.setRadius(
20.5);
18
19   cout <<
“After modifying circle1 and circle2: ” << endl;
20   cout <<
“\tcircle1.getRadius() returns ”
21      << circle1.getRadius() << endl;
22   cout <<
“\tcircle2.getRadius() returns ”
23      << circle2.getRadius() << endl;
24
25   
return 0;
26 }

The program creates two Circle objects: circlel and circle2 (lines 7-8). circle2 is created using the copy constructor by copying circlel’s data.

The program then modifies the radius in circlel and circle2 (lines 16-17) and dis­plays their new radius in lines 20-23.

Note that the memberwise assignment operator and copy constructor are similar in the sense that both assign values from one object to the other. The difference is that a new object is created using a copy constructor. Using the assignment operator does not create new objects.

The default copy constructor or assignment operator for copying objects performs a shallow shallow copy, rather than a deep copy, meaning that if the field is a pointer to some object, the address deep copy of the pointer is copied rather than its contents. Listing 11.18 demonstrates this.

Listing 11.18 ShallowCopyDemo.cpp

1 #include <iostream>
2
#include “Course.h” // Defined in Listing 11.14
3 using namespace std;
4

5 int main()
6 {
7     Course course1(
“C++”, 10);
8     Course course2(course1);
9
10    course1.addStudent(
“Peter Pan”); // Add a student to course1
11    course2.addStudent(“Lisa Ma”); // Add a student to course2
12
13    cout <<
“students in course1: ” <<
14    course1.getStudents()[
0] << endl;
15    cout <<
“students in course2: ” <<
16    course2.getStudents()[
0] << endl;
17
18   
return 0;
19 }

The Course class was defined in Listing 11.14. The program creates a Course object coursel (line 7) and creates another Course object course2 using the copy constructor (line 8). course2 is a copy of coursel. The Course class has four data fields: courseName, numberOfStudents, capacity, and students. The students field is a pointer type. When course1 is copied to course2 (line 8), all the data fields are copied to course2. Since students is a pointer, its value in course1 is copied to course2. Now both students in course1 and course2 point to the same array object, as shown in Figure 11.6.

Line 10 adds a student “Peter Pan” to course1, which is to set “Peter Pan” in the first element of the array. Line 11 adds a student “Lisa Ma” to course2 (line 11), which is to set “Lisa Ma” in the first element of the array. This in effect replaces “Peter Pan” with “Lisa Ma” in the first element of the array since both course1 and course2 use the same array to store student names. So, the student in both course1 and course2 is “Lisa Ma” (lines 13-16).

When the program terminates, course1 and course2 are destroyed. course1 and course2’s destructors are invoked to delete the array from the heap (line 10 in Listing 11.16). Since both course1 and course2’s students pointer point to the same array, the array will be deleted twice. This will cause a runtime error.

To avoid all these problems, you should perform a deep copy so that course1 and course2 have independent arrays to store student names.

Source: Liang Y. Daniel (2013), Introduction to programming with C++, Pearson; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *