1.为什么要阻止类对象的拷贝?
1)有些类,不需要拷贝和赋值运算符,如:IO类,以避免多个拷贝对象写入或读取相同的IO缓冲
2.如何阻止?
1)不定义拷贝构造函数和拷贝赋值运算符时,好心的编译器也会及时地学习雷锋好榜样帮你合成定义,即传说中的合成拷贝构造、合成拷贝赋值,所以这样阻止不了
2)c++11允许使用“=delete”将拷贝构造函数和拷贝赋值运算符定义为删除的函数,在函数参数列表后加上“=delete”即表明这个函数是删除的函数
3)删除的函数是一种这样的函数:我们虽然声明了它,但是不能使用它
4)"=delete"的主要用途是阻止类的拷贝赋值,但也可以指定给非拷贝控制成员
3.=delete和=default的区别
1)"=delete"必须出现在函数第一次声明的时候;而"=default"没有这个要求
2)语法上允许对任何函数都可以指定"=delete",不局限于类的成员函数,但一般情况下对析构函数不指定;而语法上只能对默认构造函数和五个拷贝控制成员使用"=default"
4.合成版本的拷贝成员函数可能被编译器定义为delete
1)某个数据成员的拷贝构造函数是删除的或不可访问的(private),则这个类的合成拷贝构造函数会被编译器定义为delete
2)某个数据成员的拷贝赋值运算符是删除的或不可访问的(private),或者类有一个const成员,或者类有一个引用成员,则这个类的合成拷拷贝赋值运算符会被编译器定义为delete
3)特殊情况:定义了一个移动构造函数或移动赋值运算符的必须也定义自己的拷贝成员函数,否则,它们被编译器合成的版本将为delete
4)规则总结:如果类的某个数据成员不能拷贝、赋值,则对应的合成版本的成员函数将被编译器定义为delete。
5.合成版本的构造/析构函数可能被编译器定义为delete
1)某个数据成员的析构函数是删除的或不可访问的(private),则这个类的合成析构函数会被编译器定义为delete
2)某个数据成员的析构函数是删除的或不可访问的(private),或者类有一个const成员却没有类内初始值,或者类有一个引用成员却没有类内初始值,则这个类的合成构造函数会被编译器定义为delete
6.合成版本的移动成员函数可能被编译器定义为delete
1)如果显式地用=default要求编译器生成合成移动操作,且编译器不能移动所有非static成员,则合成移动操作会被编译器定义为delete.
7.c++11以前detele的替代品
1)在c++11之前,类可以通过将其拷贝构造函数和拷贝赋值运算符声明为private来阻止拷贝,用户不能使用它们来拷贝对象,试图拷贝对象的代码在编译阶段将被标记为错误