更多 C++ 慣用法/不可複製 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);
}
- ISO/IEC 14882:2003 C++ 標準 §12.8/4,§12.8/7