在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++中沒有拷貝構造函數,這個模式實現可能比較困難。