乐趣区

C-noncopyable类

在 muduo 中,有一个 noncopyable 类,继承了该类的派生类不能被拷贝,只能被移动。涉及拷贝的函数有两个:拷贝构造函数和拷贝复制操作符。将这两个方法声明为不可访问或者删除(=delete),即可达到不可拷贝的效果。

将函数声明为private

将拷贝构造函数和拷贝复制操作符声明为 private,能阻止编译器创建这两个函数,同时阻止用户调用它们,从而达到阻止拷贝的效果。实现如下:

class noncopyable {
public:
    ...
private:
    
    noncopyable(const noncopyable&);
    noncopyable& operator=(const noncopyable&);
};

《Effective C++》第三版 条款 06介绍的就是这种实现。

使用方法:

class myClass : private noncopyable {};

注意:此处一定要使用 private 继承,以防止 member 函数和 friend 函数访问。

C++ 11 下使用 delete 关键字

C++ 11 下可以使用 delete 关键字可以很方便地实现。

class noncopyable {
public:
    
    noncopyable(const noncopyable&) = delete;
    noncopyable& operator=(const noncopyable&) = delete;
};

Boost 中的实现

boot::noncopyable的实现结合了前面两种方法:

class noncopyable {
protected:
    // 默认的构造函数和析构函数是 protected,// 不允许创建 noncopyable 实例,但允许子类创建实例
    //(即允许派生类构造和析构)。noncopyable() = default;
    ~noncopyable() = default;

private:
    // 使用 delete 关键字禁止编译器自动产生复制构造函数和复制赋值操作符。noncopyable(const noncopyable&) = delete;
    const noncopyable& operator=(const noncopyable&) = delete;
};

阻止拷贝的限制

为什么很多人禁用拷贝(复制)构造函数中提到,阻止拷贝有几点限制:

  • 在 C ++11 之前对象必须有正常的拷贝语义才能放入容器中,禁用拷贝构造的对象无法直接放 入容器中,当然你可以使用指针来规避这一点,但是你又落入了自己管理指针的困境之中(或许使用智能指针可以缓解这一问题)。
  • C++11 中存在移动语义,你可以通过移动而不是拷贝把数据放入容器中。
  • 拷贝构造函数的另一个应用在于设计模式中的 原型模式,在 C ++ 中没有拷贝构造函数,这个模式实现可能比较困难。

参考

  • muduo
  • 为什么很多人禁用拷贝(复制)构造函数
  • C++: 不可拷贝(noncopyable)类
  • Boost noncopyable.hpp header file
  • C++ 工程实践(8):值语义
退出移动版