标签:ons 传递 拷贝赋值运算符 数组 span 接受 运算 无限循环 元素
拷贝构造函数
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
拷贝构造函数第一个参数必须是一个引用类型。此参数几乎总是一个const的引用。拷贝构造函数在几种情况下都会被隐式地使用。因此,拷贝构造函数通常不应该是explicit的。
合成拷贝构造函数
与合成默认构造函数不同,即使我们定义了其他构造函数,编译器也会为我们合成一个拷贝构造函数。
对某些类来说,合成拷贝构造函数用来阻止我们拷贝该类类型的对象。而一般情况,合成的拷贝构造函数会将其参数的成员逐个拷贝到正在创建的对象中。每个成员的类型决定了它如何拷贝。
拷贝初始化
直接初始化和拷贝初始化的差异。
string dots(10,‘,‘); //直接初始化
string s(dots); //直接初始化
string s2 = dots; //拷贝初始化
当使用直接初始化时,我们实际上是要求编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。当我们使用拷贝初始化时,我们要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换。
拷贝初始化通常使用拷贝构造函数来完成。拷贝初始化是依靠拷贝构造函数或移动构造函数来完成的。
拷贝初始化不仅在我们用=定义变量时会发生,在下列情况下也会发生
?将一个对象作为实参传递给一个非引用类型的形参。
?从一个返回类型为非引用类型的函数返回一个对象。
?用花括号列表初始化一个数组中的元素或一个聚合类中的成员。
参数和返回值
拷贝构造函数被用来初始化非引用类类型参数,这一特性解释了为什么拷贝构造函数自己的参数必须是引用类型。如果其参数不是引用类型,则调用永远也不会成功——为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又必须调用拷贝构造函数,如此无限循环。
拷贝初始化的限制
vector<int> v1(10); //直接初始化
vector<int> v1 = 10; //错误:接受大小参数的构造函数是explicit的
如果我们希望使用一个explicit构造函数,就必须显式的使用:
void f(vector<int>); //f的参数进行拷贝初始化
f(10); //错误:不能用一个explicit的构造函数拷贝一个实参
f(vector<int>(10)); //正确:从一个int直接构造一个临时vector
如果我们希望使用一个explicit构造函数,就必须显式的使用:
编译器可以绕过拷贝构造函数
编译器被允许将下面的代码string null_book = "9-999-99999-9";
给写成string null_book("9-999-99999-9");//编译器略过了拷贝构造函数。
拷贝赋值运算符
类通过拷贝赋值运算符控制其对象如何赋值。
重载赋值运算符
重载赋值运算符本质上是函数,其名字由operator关键字后接表示要定义的运算符的符号组成。因此,赋值运算符就是一个名为operator=的函数。类似于任何其他函数,运算符函数也有一个返回类型和一个参数列表。
值得注意的是,标准库通常要求保存在容器中的类型要具有赋值运算符,且其返回值是左侧运算对象的引用。
合成拷贝赋值运算符
与处理拷贝构造函数一样,如果一个类未定义自己的拷贝赋值运算符,编译器会为他它生成一个合成拷贝赋值运算符。类似拷贝构造函数,对于某些类,合成拷贝构造运算符用来禁止该类型对象的赋值。
析构函数
三/五法则
使用=default
阻止拷贝
c++类的拷贝、赋值与销毁(拷贝构造函数、拷贝赋值运算符析构函数)
标签:ons 传递 拷贝赋值运算符 数组 span 接受 运算 无限循环 元素
原文地址:http://www.cnblogs.com/mu-ye/p/7898728.html