我繼續讀那swap()
操作,像這樣的例子:關於swap()操作的異常安全 - 有什麼問題?
template<class T>
void swap (T &a, T &b)
{
T temp (a);
a = b;
b = temp;
}
是有問題的,當我們面對的是異常安全。
它有什麼問題? 此外,我們如何解決它?
我繼續讀那swap()
操作,像這樣的例子:關於swap()操作的異常安全 - 有什麼問題?
template<class T>
void swap (T &a, T &b)
{
T temp (a);
a = b;
b = temp;
}
是有問題的,當我們面對的是異常安全。
它有什麼問題? 此外,我們如何解決它?
在一般實現中,假設T
的任何操作都可以使用throw
,那麼您不能提供強大的異常保證,這意味着完全保留狀態與異常事件操作之前的狀態完全相同。即使在T
每個操作提供了強大的異常保證:
template<class T>
void swap (T &a, T &b)
{
T temp (a); // [1]
a = b; // [2]
b = temp; // [3]
}
如果[1]兩罰全中,輸入保持不變,這是很好的。如果[2]拋出,並且假設強有力的例外保證,那麼這些值仍然未被觸發,這是很好的。但是,如果拋出[3],a
已被修改,這意味着在異常傳播到堆棧之後,調用者將留下一個既不是原始狀態也不是最終狀態的狀態。
編輯:此外,我們如何解決它呢?
沒有通用的解決方案。但在大多數情況下,您可以爲您的類型提供異常安全swap
操作。考慮vector<T>
,它通過使用三個指針(begin
,end
,capacity
)在內部管理它的狀態。一般swap
以上皆可拋(不分配,用於內部T
建設者可能會引發...),但它是微不足道提供無拋出swap
實現:
template <typename T>
class vector {
T *b,*e,*c;
public:
void swap(vector<T>& rhs) {
using std::swap;
swap(b, rhs.b);
swap(e, rhs.e);
swap(c, rhs.c);
}
//...
};
template <typename T>
void swap(vector<T>& lhs, vector<T>& rhs) {
lhs.swap(rhs);
}
由於指針的複製不能扔,上面的swap
提供了無投票保證,如果您始終按照上述模式執行swap
(using std::swap;
後跟非限定呼叫swap
),那麼它將被ADL視爲比std::swap
更好的匹配。
丹尼爾是對的,當然。
但是你不應該忘記,當涉及到異常安全時,swap主要被認爲是解決方案的一部分(「複製和交換習慣用法」),而不是問題。剩下的問題是,如果你採用這個習慣用法,你必須確保交換的拷貝構造函數可以調用,不要拋出異常,這是Daniel解釋的原因。
異常的來源一直是解釋
,但你可以通過鑄造參數unsigned byte*
和字節加快調換字節sizeof(T)
注意:不調用任何構造避免異常或在其上可能違反某些先決條件時,有一些參考自正在進行的對象的析構函數(當a
指向b
交換a
之後將指向a
)
這就是D標準庫中的交換是如何做到的(在檢查自引用之後)
+1我會寫同樣的東西。與[本文](http://www.boost.org/community/exception_safety.html)的鏈接將是一種幫助,對那些想要詳細瞭解基於合同的異常安全的人員很有幫助。 – Nawaz 2012-07-14 17:30:58