C++11:类的删除函数(=delete关键字、阻止构造、阻止拷贝、private阻止拷贝控制)

一、删除函数的概念

  • 大多数类定义了拷贝构造函数和拷贝赋值运算符,但对某些类来说,这些操作时没有意义的,例如,iostream类阻止了拷贝,以避免多个对象写入或读取相同的IO缓冲
  • 但是由于我们即使不给出类的拷贝构造函数和拷贝赋值运算符,但是编译器会有他们的默认版本,因此在新标准下,我们使用“=delete”来将不想要的函数定义成删除的函数,我们将不能以任何方式使用它们
  • 删除函数主要用来阻止类的拷贝

二、删除函数的格式

  • 在函数的参数列表后面加上“=delete”来指出我们希望将其删除
struct NoCopy{
    NoCopy()=default;      //使用合成的默认构造函数
    NoCopy(const NoCopy&)=delete;  //阻止拷贝
    NoCopy &operator=(const NoCopy&)=delete; //阻止赋值
    ~NoCopy()=default; //使用合成的析构函数
};

三、删除函数的特点

  • 删除函数是这样的一种函数:我们虽然声明了它们,但不能以任何方式使用它们

与=default的不同

  • 与=default不同,=delete必须出现在函数第一次声明的时候
  • 我们可以对任何函数指定=delete(除析构函数外),但是我们只能对编译器可以合成的默认构造函数或拷贝控制成员使用=default

三、析构函数不能定义为删除的成员

  • 需要注意的是:我们不能删除析构函数。因为析构函数被删除了,就无法销毁此类型的对象了

如果一个类的析构函数被删除了:

  • 编译器将不允许定义该类型的变量或创建该类的临时对象(因为该类不能被删除销毁了)
  • 如果一个类中有一个成员,该成员为类类型,且该类类型删除了析构函数,则我们也不能定义这个类的变量或临时对象(因为该类的成员无法被删除,间接导致这个类也无法被删除销毁)
  • 虽然我们不能定义这种类型的变量或成员,但是可以动态分配这种类型的对象,但是动态分配之后就不能释放这个对象了
struct NoDtor{
    NoDtor() = default; //使用合成的默认构造函数
    ~NoDtor() = delete; //我们不能销毁NoDtor类型的对象
};

NoDtor nd;  //错误,NoDtor的析构函数时删除的
NoDtor *p=new NoDtor(); //正确,但是我们不能delete p
delete p; //错误,NoDtor的析构函数是删除的

四、类的某些函数可能是删除的

  • 引入:我们知道如果我们未定义拷贝构造函数、拷贝赋值运算符或构造函数、析构函数,系统会相应有一个默认的版本(也称为“合成的”)

对于某些类来说,编译器可能将这些合成的成员定义为删除的函数:

C++11:类的删除函数(=delete关键字、阻止构造、阻止拷贝、private阻止拷贝控制)_第1张图片

  • 上面这些规则的含义是:如果一个类有数据成员不能默认构造、拷贝、赋值或销毁,则对应的成员函数将被定义为删除的

C++11:类的删除函数(=delete关键字、阻止构造、阻止拷贝、private阻止拷贝控制)_第2张图片

五、private阻止拷贝控制

  • 在这个C++11标准发布之前,类为了阻止拷贝构造函数和拷贝赋值运算符,而将它们声明为private来阻止拷贝
  • 在下面的代码中拷贝构造函数和拷贝赋值运算符被定义为private,因此这两个函数无法被外部所访问,因此也就无法进行类之间的拷贝了
class PrivateCopy{
    //拷贝构造函数和拷贝赋值运算符被定义为private
    PrivateCopy(const PrivateCopy&);
    PrivateCopy &operator=(const PrivateCopy&);
public:
    PrivateCopy()=default;
    ~PrivateCopy();
};

缺陷:

  • 虽然拷贝构造函数和拷贝赋值运算符被定义为private,类外无法直接访问这两个函数了,但是友元和成员函数仍旧可以拷贝对象

解决方法:

  • 为了阻止友元和成员函数进行拷贝,我们将这些拷贝控制成员声明为private,但不定义他们(声明但不定义一个成员函数是合法),这样当试图拷贝对象的用户代码将在编译阶段被标记为错误,拷贝操作将会导致链接时错误

六、总结

  • 希望阻止拷贝的类应该使用=delete来定义它们自己的拷贝构造函数和拷贝赋值运算符,而不应该将它们声明为private的

你可能感兴趣的:(C++11/17)