2016-01-18 43 views
3

我有一個簡單的RAII包裝管理某些資源。這裏的接口:如何刪除移動賦值運算符並保​​留與std容器的兼容性?

struct ResourceWrapper 
{ 
    explicit ResourceWrapper(RESOURCE resource); 
    ResourceWrapper(const ResourceWrapper& other); 
    ResourceWrapper& operator=(const ResourceWrapper& other); 
    ~ResourceWrapper(); 

    ResourceWrapper(ResourceWrapper&& other) = delete; 
    ResourceWrapper& operator=(ResourceWrapper&& other) = delete; 
}; 

的這裏的問題是,我不能再儘快將此類std容器和算法,我明確地刪除移動賦值運算符。顯然,我確實需要刪除或正確實施它,因爲我剛剛學會了艱難的方式。

另一種選擇是通過常規賦值操作符實現移動賦值,但我不確定如何正確執行。我想我需要像std::remove_reference這樣的東西?我想知道它是否會刪除太多參考文獻,並導致創建不必要的臨時對象。

+0

你阻止移動,但促進複製?聽起來怪怪的。它是什麼資源? –

+0

@DavidHaim:確實如此。無論它是什麼資源都無所謂,我只想盡可能少地使用代碼。我不能放棄複製,但我可以放棄移動。 –

+1

放下移動的方法是不定義它,你所做的不是「放下移動」,而是「毒素移動,因此不可能複製右值」。這不一樣。 –

回答

12

很明顯,我確實需要刪除或正確實施它,因爲我剛剛學會了艱難的方式。

不,你不知道。

你的類有一個用戶定義的複製構造函數,拷貝賦值操作符和析構函數,所以編譯器將定義移動賦值運算符爲您服務。

因此,只要停止嘗試刪除它,該類將被複制而不是移動。

隨着已刪除移動操作,您不能複製類型的右值,即變得非常難以用作值類型(包括在容器中)。隨着沒有移動操作它只會做rvalues的深層副本,這是安全的,可能是你想要的。

如果您希望課程完全不可移動並且不可複製,則刪除移動操作纔有意義。像對象身份至關重要的互斥體類型,而不是它的價值。擁有可刪除移動的可複製類型永遠沒有意義。

+0

我強烈懷疑它沒有發生,我正在處理的錯誤是由默認移動分配引起的。我猜我必須正確實施移動任務才能測試該假設? –

+1

@VioletGiraffe爲了測試這樣一個假設(這將表明你正在使用的編譯器中存在一個錯誤),你可以簡單地按照副本實現移動:'ResourceWrapper(ResourceWrapper && other):ResourceWrapper(other){}'。注意後者確實會調用copy ctor。 – Angew

+0

@Angew:構造函數不是問題,賦值是。不是'ResourceWrapper&operator =(ResourceWrapper && other){return * this = other;}'遞歸嗎?或者,如果我使用'return * this = std :: forward(other)',它只會是遞歸嗎? –