[英]Why do we use copy and swap when using assignment operator?
使用復制和交換方法時,我對賦值運算符有疑問。
String & operator = (String s) // the pass-by-value parameter serves as a temporary
{
s.swap (*this); // Non-throwing swap
return *this;
}// Old resources released when destructor of s is called.
假設我們有一個很好的復制構造函數,它可以深度復制所有指針和動態分配的變量。
那么,上面的代碼和下面的代碼有什么區別?
String & operator = (String s) // the pass-by-value parameter serves as a temporary
{
return s;
}
因為我們有一個好的復制構造函數,所以我認為在operator =函數內部創建了另一個對象s。 那么,使用非拋出交換函數有什么意義呢?
主要區別在於第二個operator=
根本不更改當前對象(即*this
)。
String a, b;
b = a; // b is not changed at all
並請注意,第二個operator=
通過引用返回s
(退出函數時將被銷毀),因此它只是一個懸掛的引用。
更籠統地說,我們使用復制和交換慣用法來提供強大的異常安全保證,這類似於提交或回滾語義; 如果操作由於異常而終止,則程序狀態將保持不變。
String & operator = (String s) // Copy construct s. If exception happens here,
// s won't be constructed,
// and the state of the current object (*this) won't be changed
{
s.swap (*this); // Use non-throwing swap to commit the change
return *this; // Non-throwing operation
}
區別在於,在第二個代碼塊中,您將創建String
對象的副本s
,返回對其的引用,然后該副本在作用域出口處被破壞,這將導致程序具有未定義的行為。
有幾個主要區別:
賦值運算符應返回*this
(並且幾乎總是如此)。 這就是使鏈接分配成為可能的原因。
String s1, s2, s3;
s1 = s2 = s3; // Now all strings ave the same value.
而是,您返回對局部變量的引用。 然后,由於它沒有指向有效的內存位置,因此成為懸掛的參考。
另外,賦值運算符必須更改分配的對象,這在您的代碼中不會發生。
最后,為什么我們完全需要非拋出交換? 假設您的賦值運算符拋出異常。 分配失敗后,分配對象的狀態是什么?
某些實現可能導致對象處於無效狀態,因為在更改對象的中間拋出了異常。
這就是交換發生的地方。由於交換從未拋出,因此我們可以確保分配的對象處於有效狀態。 如果在交換之前引發異常,則該對象仍具有其舊值,如果在交換之后引發該對象,則其具有新值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.