Copy constructor

Functions taking objects as arguments

Let us have a look at the program below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream> class A { public: A(const std::string & name) : _name(name) { std::cout << "Object \"" << _name << "\" created!" << std::endl; } ~A() { std::cout << "Object \"" << _name << "\" destructed!" << std::endl; } private: std::string _name; }; void func(A arg) { } int main() { A a("Object"); std::cout << "Before function call." << std::endl; func(a); std::cout << "After function call." << std::endl; return 0; }

In the program above, the constructor A(const std::string & name) is called once and the destructor ~A is called twice. How is that possible? Since the argument of the function func is not a reference, it copies the value it receives. Therefore, in the call of the function func from above, the object arg is created by copying the members of a, instead of calling its constructor which header is A(const std::string & name). This is the reason why the string "Object "object" created!" has no been printed to the console when the arg has been created.

When a copy of an object is made, a constructor called the copy constructor is used to create the object, not the assignment operator =. The copy constructor is a constructor overload that is automatically created, but it is possible to define it manually to specify its behavior. The default constructor does the same thing as the default assignment operator overload taking two objects of the same class as operands does: It copies the members of the argument to the object.

Defining the copy constructor

The copy constructor is an overload of the constructor that takes a constant reference to an object of the class.

Here, we define the copy constructor of the class A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream> class A { public: A(const std::string & name) : _name(name) { std::cout << "Object \"" << _name << "\" created!" << std::endl; } A(const A & obj) // Copy constructor. { std::cout << "Copy of \"" << obj._name << "\".\n"; _name = obj._name; } ~A() { std::cout << "Object \"" << _name << "\" destructed!" << std::endl; } private: std::string _name; }; void func(A arg) { } int main() { A a("Object"); func(a); return 0; }

As we can see, the object arg, from the function func, has been created using the copy constructor.

When is the copy constructor called?

The copy constructor of a class is used to create an object when: An object is defined with an other object of the same type as only argument for its constructor, an object is given to a function/method (Not as a reference or pointer) or an object is returned by a function/method.

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> /*Same class definition of A as above */ A func(A &arg) { return arg; // Copy constructor used to return a copy of the object 'arg'. } int main() { A a("Object"); A b(a); // Copy constructor used to copy the object a. A c = func(a); return 0; }

In the example above, the object b is created, using its copy constructor, as a copy of the object a. The function func returns an object that is a copy of the object referenced by the argument arg. That object is built using its copy constructor. The object c is created, using its assignment operator, as a copy of the temporary object returned by the function func, which is a copy of the object a.