Выбрать главу

Конструктор копии также вызывается в случае, когда один объект используется для инициализации другого.

Рассмотрим следующую простую программу.

// Вызов конструктора копии для инициализации объекта.

#include <iostream>

#include <cstdlib>

using namespace std;

class myclass {

  int *p;

 public:

  myclass(int i); // обычный конструктор

  myclass(const myclass &ob); // конструктор копии

  ~myclass();

  int getval() { return *p; }

};

// Конструктор копии.

myclass::myclass(const myclass &ob)

{

 p = new int;

 *p = *ob.p; // значение копии

 cout << "Выделение p-памяти конструктором копии.\n";

}

// Обычный конструктор.

myclass::myclass(int i)

{

 cout << "Выделение p-памяти обычным конструктором.\n";

 р = new int;

 *р = i;

}

myclass::~myclass()

{

 cout << "Освобождение р-памяти.\n";

 delete p;

}

int main()

{

 myclass a(10); // Вызывается обычный конструктор.

 myclass b = a; // Вызывается конструктор копии.

 return 0;

}

Результаты выполнения этой программы таковы.

Выделение p-памяти обычным конструктором.

Выделение p-памяти конструктором копии.

Освобождение р-памяти.

Освобождение р-памяти.

Как подтверждают результаты выполнения этой программы, при создании объекта а вызывается обычный конструктор. Но когда объект а используется для инициализации объекта b, вызывается конструктор копии. Использование конструктора копии гарантирует, что объект b выделит для своих членов данных собственную область памяти. Без конструктора копии объект b попросту представлял бы собой точную копию объекта а, а член а.р указывал бы на ту же самую область памяти, что и член b.р.

Следует иметь в виду, что конструктор копии вызывается только в случае выполнения инициализации. Например, следующая последовательность инструкций не вызовет конструктор копии, определенный в предыдущей программе:

myclass а(2), b(3);

// ...

b = а;

Здесь инструкция b = а выполняет операцию присваивания, а не операцию копирования.

Использование конструктора копии при возвращении функцией объекта

Конструктор копии также вызывается при создании временного объекта, который является результатом возвращения функцией объекта. Рассмотрим следующую короткую программу.

/* Конструктор копии вызывается в результате создания временного объекта в качестве значения, возвращаемого функцией.

*/

#include <iostream>

using namespace std;

class myclass {

 public:

  myclass() { cout << "Обычный конструктор.\n"; }

  myclass(const myclass &obj) {cout << "Конструктор копии.\n"; }

};

myclass f()

{

 myclass ob; // Вызывается обычный конструктор.

 return ob; // Неявно вызывается конструктор копии.

}

int main()

{

 myclass a; // Вызывается обычный конструктор.

 а = f(); // Вызывается конструктор копии.

 return 0;

}

Эта программа генерирует такие результаты.

Обычный конструктор.

Обычный конструктор.

Конструктор копии.

Здесь обычный конструктор вызывается дважды: первый раз при создании объекта а в функции main(), второй — при создании объекта ob в функции f(). Конструктор копии вызывается в момент, когда генерируется временный объект в качестве значения, возвращаемого из функции f().