跳轉至內容

更多 C++ 慣用法/不可複製 Mixin

來自 Wikibooks,開放世界中的開放書籍

不可複製 Mixin

[編輯 | 編輯原始碼]

防止類的物件被複制構造或相互賦值。

也稱為

[編輯 | 編輯原始碼]

很多時候,阻止複製類的物件是有意義的。例如,一個封裝網路連線的類。對於這樣的類,複製無法有意義地定義。因此,應該明確地阻止它,而不依賴於指南或程式設計師的紀律。意圖也應該透過檢視類的宣告來輕鬆識別,以提高可讀性。

解決方案和示例程式碼

[編輯 | 編輯原始碼]

定義了一個名為 non-copyable 的類,它具有私有複製建構函式和複製賦值運算子。

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

  protected:
    NonCopyable () = default;
    ~NonCopyable () = default; /// Protected non-virtual destructor
};
class CantCopy : private NonCopyable
{};

CantCopy 物件無法複製,因為私有基類 NonCopyable 的複製建構函式和複製賦值運算子對派生類不可訪問。處理這些的傳統方法是宣告一個私有複製建構函式和複製賦值,然後記錄為什麼要這樣做。但是從 noncopyable 派生更簡單、更清晰,並且不需要額外的文件。NonCopyable 的私有成員不需要定義。NonCopyable 也可以歸類為自上而下的 mixin,因為它定義了一個可重複使用的模組,該模組從“上方”將“不可複製性”功能“混合”到派生類中。CRTP 解決方案如下。(這允許在多重繼承中進行空基最佳化 [參見討論頁])。

template <class T>
class NonCopyable
{
  public: 
    NonCopyable (const NonCopyable &) = delete;
    T & operator = (const T &) = delete;

  protected:
    NonCopyable () = default;
    ~NonCopyable () = default; /// Protected non-virtual destructor
};
class CantCopy : private NonCopyable <CantCopy>
{};

顯式複製建構函式

值得注意的是,C++ 允許另一種方法來控制複製構造。一個顯式複製建構函式將阻止編譯器隱式呼叫複製建構函式。即,按值傳遞物件和按值返回物件將被停用,因為具有顯式複製建構函式的類。但是,允許進行顯式複製。在 gcc 上,使用 -fno-elide-constructors 選項停用複製消除。此選項有助於觀察(實際上並未觀察!)返回值最佳化的效果。通常不建議停用此重要的最佳化。

struct NoImplicitCopy
{
  NoImplicitCopy () = default;
  explicit NoImplicitCopy (const NoImplicitCopy &) = default;
};

NoImplicitCopy foo()   // Compiler error because copy-constructor must be invoked implicitly to return by value.  
{
  NoImplicitCopy n;
  return n;
}

void bar(NoImplicitCopy n)   // Compiler error because copy-constructor must be invoked implicitly to pass by value.
{
}

int main(void)
{
  NoImplicitCopy n;
  NoImplicitCopy x(n);       // This is fine. explicit copy.
  n = foo();
  bar(n);
}

已知用途

[編輯 | 編輯原始碼]

boost::noncopyable

[編輯 | 編輯原始碼]

奇怪的遞迴模板模式

參考文獻

[編輯 | 編輯原始碼]
  1. ISO/IEC 14882:2003 C++ 標準 §12.8/4,§12.8/7
華夏公益教科書