定义:
- 如果使用等号(=)初始化一个变量,实际上执行的是“拷贝初始化”,编译器把等号右侧的初始值拷贝到新创建的对象中去。
- 与之相反,如果不使用等号,则执行的是“直接初始化”
示例:
string dots(10,'.'); //直接初始化
string s(dots); //直接初始化
string s2 = dots; //拷贝初始化
string null_book = "9-999-99999-9"; //拷贝初始化
string nines = string(100,'9'); //拷贝初始化
注:
直接初始化实际上是要求编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数
拷贝初始化实际上是要求编译器将右侧运算对象拷贝到正在创建的对象中,通常用拷贝构造函数来完成
拷贝初始化发生的其他情况:
拷贝初始化不仅在用=定义变量时发生,下列情况也发生
- 将一个对象作为实参传递给非引用类型的形参时
- 从一个返回类型为非引用类型的函数返回一个对象
- 当初始化标准库容器或是调用其insert或push成员时(与之相对,用emplace成员创建的元素都进行直接初始化)
拷贝构造函数的形参必须是引用类型的原因:
如果不是引用类型,为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环,造成错误。
拷贝初始化的限制:
当拷贝构造函数前面加了一个explicit关键字时,调用拷贝构造函数不能进行隐式类型转换,但可以进行显示类型转换,如:
vector<int> v1(10); //正确:直接初始化
vector<int> v2 = 10;//错误:接受大小参数的构造函数是explicit的
void f(vector<int>);//f的参数进行拷贝初始化
f(10);//错误:不能用一个explicit的构造函数拷贝一个实参
f(vector<int>(10));//正确:可以进行显示类型转换(f的参数必须接收一个对象)
参考:《C++ Primer》