Ответ
Конструктор копирования вызывается для создания нового объекта как копии существующего объекта того же типа. Основные сценарии:
- Явная инициализация копией:
MyClass obj1; MyClass obj2(obj1); // Прямой вызов конструктора копирования MyClass obj3 = obj1; // Копирующая инициализация (также вызывает конструктор копирования) - Передача аргумента в функцию по значению:
void foo(MyClass param); // Функция принимает объект по значению MyClass obj; foo(obj); // При вызове `param` создаётся копированием `obj` - Возврат объекта из функции по значению (в определённых условиях):
MyClass createObject() { MyClass localObj; return localObj; // До C++17 мог вызываться конструктор копирования/перемещения. // Начиная с C++17, здесь гарантировано применяется оптимизация // (mandatory copy elision), и вызова конструктора не происходит. } - Инициализация элементов или базовых классов: При создании объекта, члены которого или базовые классы инициализируются другим объектом.
Практический пример:
#include <iostream>
class Resource {
public:
Resource() { std::cout << "Resource defaultn"; }
Resource(const Resource&) { std::cout << "Resource copyn"; }
};
class MyClass {
Resource res;
public:
MyClass() { std::cout << "MyClass defaultn"; }
MyClass(const MyClass& other) : res(other.res) { // Вызов конструктора копирования Resource
std::cout << "MyClass copyn";
}
};
void byValue(MyClass c) { /* ... */ }
int main() {
std::cout << "--- Creating original ---n";
MyClass original;
std::cout << "n--- Copy initialization ---n";
MyClass copy = original; // Вызов MyClass::MyClass(const MyClass&)
std::cout << "n--- Passing by value ---n";
byValue(original); // Ещё один вызов конструктора копирования
return 0;
}
Важно: Современный C++ (C++11 и новее) стремится заменять копирование на перемещение (через конструктор перемещения) там, где это возможно, например, при возврате локальной переменной из функции.