Этот сайт использует cookies. Продолжение работы с сайтом означает, что Вы согласны!
Конструктор копирования
В случае присваивания одного объекта другому при объявлении, а также при передаче объекта в качестве параметра в функцию и возврате объекта из функции вызывается особый конструктор — конструктор копирования. Если конструктор копирования не определен, то используется конструктор копирования по умолчанию. В этом случае создается побитовая копия объекта. Если внутри класса производится динамическое выделение памяти, то обязательно следует определить конструктор копирования явным образом, так как создание побитовой копии в этом случае недопустимо. Конструктор копирования имеет следующий формат:
<Название класса>(const <Название класса> &<Название объекта>);
Название конструктора копирования совпадает с названием класса. В качестве параметра конструктор принимает константную ссылку на копируемый объект. Тип возвращаемого значения не указывается. Продемонстрируем использование конструктора копирования на примере (листинг 13.9).
Листинг 13.9. Конструктор копирования
#include <iostream>
class C {
int x_, y_;
public:
C(int x, int y): x_(x), y_(y) { } // Обычный конструктор
C(const C &obj)
: x_(obj.x_), y_(obj.y_) { // Конструктор копирования
std::cout << "copy" << std::endl;
}
~C() { // Деструктор
std::cout << "~C()" << std::endl;
}
void setX(int x) { x_ = x; }
void dump() {
std::cout << x_ << ' ' << y_ << std::endl;
}
};
void func1(C obj) { } // Передача объекта через параметр
C func2(int x) {
return C(x, 10); // Возврат объекта из функции (RVO)
}
C func3(int x) {
C obj(x, 11);
return obj; // Возврат объекта из функции (NRVO)
}
int main() {
C obj1(40, 30);
C obj2 = obj1; // Вызывается конструктор копирования
obj2.dump(); // 40 30
func1(obj1); // Вызывается конструктор копирования
obj2 = obj1; // Конструкторы не вызываются!!!
// Требуется перегрузка оператора =
// По умолчанию побитовая копия
obj2.setX(5);
obj1.dump(); // 40 30
obj2.dump(); // 5 30
// Возврат объекта из функции
C obj3 = func2(10);
obj3.dump(); // 10 10
C obj4 = func3(20);
obj4.dump(); // 20 11
return 0;
}
Обратите внимание на то, что при простом присваивании объектов (вне объявления) конструктор копирования не вызывается. В этом случае нужно перегружать оператор присваивания. По умолчанию создается побитовая копия объекта.
Следует также учитывать, что при возврате объекта из функции конструктор копирования может не вызываться из-за оптимизаций, выполняемых компилятором. Существуют два варианта, при которых компилятор может не создавать временный объект и не вызывать конструктор копирования:
RVO
(return value optimization
) — объект создается в инструкцииreturn
(например, как внутри функцииfunc2()
из листинга 13.9);NRVO
(named return value optimization
) — объект создается внутри функции и возвращается инструкциейreturn
(например, как внутри функцииfunc3()
из листинга 13.9).
Некоторые компиляторы (особенно старые) не выполняют оптимизацию (в частности при варианте NRVO
) и вызывают конструктор копирования. В проекте Test64
оптимизация выполняется при обоих вариантах, поэтому конструктор копирования при возврате объекта из функции не вызывается.
Помощь сайту
ЮMoney (Yandex-деньги): 410011140483022
ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов