3 回答

TA貢獻1839條經驗 獲得超15個贊
復制構造函數對曾經是原始內存的對象執行首次初始化。賦值運算符OTOH用新值覆蓋現有值。通常涉及解散舊資源(例如,內存)并分配新資源。
如果兩者之間有相似之處,那就是賦值運算符執行銷毀和復制構造。一些開發人員過去實際上是通過就地銷毀,然后是布局復制構造來實現分配的。但是,這是一個非常糟糕的主意。(如果這是派生類分配期間調用的基類的賦值運算符,該怎么辦?)
swap正如Charles所建議的,如今通常被認為是規范用語的是:
MyClass& operator=(MyClass other)
{
swap(other);
return *this;
}
這使用了復制構造(注意other已復制)和銷毀(它在函數末尾被銷毀)-并且它也以正確的順序使用它們:銷毀(必須失?。┲暗臉嬙欤赡苁。?。

TA貢獻1812條經驗 獲得超5個贊
有些事情困擾著我:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
首先,當我的思想是“復制”時,讀“交換”一詞會激怒我的常識。另外,我對這個幻想的目的提出了質疑。是的,在構造新的(復制的)資源時,任何異常都應該發生在交換之前,這似乎是一種確保所有新數據都被填充后才能上線的安全方法。
沒關系。那么,交換之后發生的異常又如何呢?(當臨時對象超出范圍時,舊資源被破壞時)從分配用戶的角度來看,該操作失敗了,但沒有失敗。它具有巨大的副作用:復制確實發生了。只是某些資源清除失敗。即使從外部看來操作失敗,目標對象的狀態也已更改。
因此,我建議不要“交換”來進行更自然的“轉移”:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
transfer(tmp);
return *this;
}
仍然存在臨時對象的構造,但是下一個直接的操作是在將源的資源移動到目的地之前,釋放目標的所有當前資源(并且為NULL,這樣它們就不會被雙重釋放)。
我提出了{構造,破壞,移動}而不是{構造,移動,破壞}。此舉是最危險的舉動,是在解決所有其他問題后采取的最后一步。
是的,無論哪種方案,銷毀失敗都是一個問題。數據已損壞(在您不認為是復制時復制)或丟失(在您不認為是被釋放時釋放)。丟失總比損壞好。沒有數據比壞數據更好。
轉移而不是交換。無論如何,這是我的建議。
- 3 回答
- 0 關注
- 458 瀏覽
添加回答
舉報