直接初始化和拷贝初始化
2021-03-02
拷贝初始化底层是先调用构造函数创建一个临时变量,再将临时变量通过拷贝构造函数创建新变量。考虑如下过程
class A{
public:
A() { cout << "default constructor" << endl; }
A(const string& _str):str(_str) { cout << "constructor" << endl; }
explicit A(const A& a) { cout << "copy constructor" << endl; }
string str;
}
int main() {
A a1; // direct initialiazation
A a2(string("hi")); // direct initialiazation
A a3 = string("hi"); // error, string("hi") can't
// implicit convert to A
// (copy initialiazation)
A a4 = a2; // the same as above
// a2 can't implicit convert to A
// by call copy constructor
}
拷贝初始化发生情况
- 用
=
定义变量时
string s1("hi"); // direct initialiazation
string s2 = s1; // copy initialiazation
- 将一个对象作为实参传递给一个非引用类型的形参
void Foo(string s) {
}
Foo(s1); // copy initialiazation
- 从一个返回类型为非引用类型的函数返回一个对象
string Foo2(){
string s("hi");
return s;
}
Foo2(); // copy initialiazation
- 用花括号列表初始化一个数组中的元素或一个聚合类中的成员
// copy initialiazation
string strs[] = {"This", "is", "copy", "initialiazation"};
struct Data {
int x;
int y;
};
// copy initialiazation
Data dt = {0, 0};
三五法则
- 拷贝构造函数
- 拷贝赋值运算符
- 析构函数
- 移动构造函数
- 移动赋值运算符
-
需要析构函数的类也需要拷贝和赋值操作
需要息高函数一般是有内存要手动释放. 那么拷贝时也要手动管理这部分内存.
-
需要拷贝操作的类也需要赋值操作, 反之亦然
考虑这样一个例子, 假设每个类具有独一无二的序号, 那么每次拷贝构造出一个新的类都需要一个新的序号, 同时, 类赋值的时候要避免将序号赋值出去. 但是, 这个类不需要自定义析构函数.