拷贝构造函数会在以下几种场景中被调用:
1. 用一个对象显式初始化另一个对象。
2. 对象按值传递给函数。
3. 函数按值返回对象。
4. 将对象插入到容器中。
5. 明确调用拷贝构造函数。
1. 当用一个对象显式初始化另一个对象时
MyClass obj1("Hello");
MyClass obj2 = obj1; // 调用拷贝构造函数
解释:
obj2 是一个新对象,初始化时使用 obj1。
这会调用拷贝构造函数。
2. 当对象以值传递给函数时
void printObject(MyClass obj) { // 这里 obj 是按值传递obj.print();
}int main() {MyClass obj1("Hello");printObject(obj1); // 调用拷贝构造函数return 0;
}
解释:
函数的参数 obj 是按值传递的,因此会创建 obj1 的副本,调用拷贝构造函数。
3. 当函数返回一个对象时(按值返回)
MyClass createObject() {MyClass obj("Hello");return obj; // 调用拷贝构造函数
}int main() {MyClass obj2 = createObject(); // 调用拷贝构造函数return 0;
}
解释:
函数返回局部对象时,会调用拷贝构造函数将 obj 返回给调用者。
优化:C++11/17 的 返回值优化(RVO) 和 移动语义 会在某些情况下避免调用拷贝构造函数。
4. 在容器中插入对象时
#include <vector>int main() {std::vector<MyClass> vec;MyClass obj("Hello");vec.push_back(obj); // 调用拷贝构造函数return 0;
}
解释:
push_back 需要将 obj 复制到容器中,因此会调用拷贝构造函数。
5. 明确调用拷贝构造函数
你可以显式地调用拷贝构造函数来创建对象:
MyClass obj1("Hello");
MyClass obj2(obj1); // 调用拷贝构造函数
解释:
显式创建 obj2,并用 obj1 进行初始化。
注意事项
避免不必要的拷贝:
如果对象较大,尽量使用 按引用传递 或 按引用返回 来避免拷贝。
示例:
void printObject(const MyClass& obj); // 使用 const 引用避免拷贝
C++11 引入移动语义:
移动构造函数可以避免拷贝,直接转移资源,从而提高性能。
示例:
vec.push_back(std::move(obj)); // 调用移动构造函数
返回值优化(RVO):
编译器会优化返回值,将对象直接构造到目标位置,避免调用拷贝构造函数。