2013-07-04 102 views
21

對於不可移動類型,以下(從最佳實踐角度)是否足夠?是否足以刪除operator =(Type type)?

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

或者我是否必須分別刪除複製/移動賦值運算符?這裏還需要析構函數嗎?

+1

你試圖刪除的操作符是'A&operator =(const A&)',我認爲 – porges

+1

@Porges:不,我想刪除'A&operator =(const A&)'**和**' A&operator =(A &&)'。 – ronag

回答

8

是的,聲明覆制構造函數和複製賦值運算符爲deleted就足夠了。由於您聲明瞭複製構造函數和複製賦值運算符,因此不會自動生成移動構造函數和移動賦值運算符。您不需要明確聲明它們deleted

從§12.8/ 9(強調)

如果一個類X的定義不明確宣佈此舉的構造函數,一個將被隱式聲明爲默認當且僅當
- X沒有一個用戶聲明的拷貝構造函數,
- X沒有一個用戶聲明的拷貝賦值運算符,
- X沒有一個用戶聲明的舉動賦值運算符,
- X沒有用戶聲明的析構函數,和
- 移動構造函數不會被隱式定義爲刪除。

從§12.8/ 20(強調)

如果一個類X的定義不明確宣佈的舉動賦值運算符,一個將被隱式聲明爲默認當且僅當
- X沒有一個用戶聲明的拷貝構造函數,
- X沒有一個用戶聲明的移動構造函數,
- X沒有一個用戶聲明的拷貝賦值運算符,
- X沒有用戶聲明的析構函數,並且
- 移動賦值運算符不會被隱式定義爲已刪除。

+1

這是最新的規則嗎?我記得在標準化過程中對這些規則進行了很多討論和修改。 – ronag

+1

以上內容來自C++ 11標準(ISO 14882-2012)。有一個C++ 14提案([N3578 - The Rule of Five]](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3578.pdf)),它可能就是你的想法,如果獲得批准,你可以從你的例子中刪除_either_ copy constructor或copy assignment operator,並獲得相同的效果,聲明它們都被刪除。 –

3

根據[class.copy]/17 operator=(A)是一個有效的拷貝賦值運算符,所以是的,它聲明刪除,因此隨着缺失的拷貝構造函數會使類是足以抑制隱性移動賦值運算符和不可複製和不可移動。

您的類比需要的更復雜,雖然,你需要的是:

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

的用戶聲明的拷貝構造函數抑制隱性轉移構造函數和用戶聲明的拷貝賦值運算符抑制隱性移動分配運營商。

但是,operator=(A)窗體是非慣用的,所以我傾向於使用operator=(const A&) = delete無論如何。它具有相同的效果。

N.B.沒有理由宣佈已刪除的功能是私人的,事實上它會導致更糟糕的診斷。根據我的經驗,公開和刪除工作更好。

也是這裏需要的析構函數嗎?

需要什麼?這取決於你的默認構造函數的作用。

+0

也許這是一個好主意,讓用戶定義的析構函數,只是爲了尊重[三項規則](https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29)(或五項),如果沒有其他原因的話。 –

+2

我不'我認爲'operator =(A)'是特別單一的,在支持編譯器的C++ 11之後(甚至在此之前)它已經被廣泛地使用,當然這沒有什麼區別*在那裏它只被刪除 - 但是當*實施時*我傾向於建議使用新的習慣用法。 –

+0

@KonradRudolph,當聲明一個複製賦值運算符純粹是爲了刪除它的目的我將使用'operator =(const A&)'作爲與拷貝構造函數的對稱性和一致性,如果沒有其他的話。 「A(A)'顯然不是有效的拷貝構造函數。 –