簡體   English   中英

為什么在使用賦值運算符時使用復制和交換?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM