2013-10-25 51 views
17

我想寫容器類。此容器具有兩個專業化的插入方法 - 首先使用複製構造函數將數據從一個容器複製到另一個容器元素。如果複製構造函數拋出異常,我只是撤消對容器的所有更改,就像什麼都沒有發生。異常安全代碼和移動語義

第二個專業化使用移動構造函數,這就是事情變得複雜的地方。當我將元素從一個容器移動到另一個容器元素時,移動構造函數會拋出異常。如果發生這種情況 - 當一些元素被移動並且其他元素停留在原始位置時,我的狀態非常混亂。如果我嘗試將元素移回 - 我可以得到另一個異常。

是否有可能以異常安全的方式編寫類似這樣的內容或異常安全和移動語義是互斥的?

回答

22

使用std::move_if_noexcept編寫異常敏感的代碼時,但仍然希望在編譯時安全地使用移動語義。

有關更多詳情,請參閱Scott Meyers' talk at GoingNative 2013。 PS:哦,是的,請記住,如果你的東西不是可複製的可構建的,那麼無論你的移動構造函數的throw/nothrow如何,你都會移動它。

+0

我沒有得到「PS」。你能詳細說明一下嗎? –

+1

如果你的舉動可以拋出,std :: move_if_noexcept回退來複制。但!如果你的東西沒有拷貝構造函數,std :: move_if_noexcept會說'Meh'並將其移動(它還能做什麼?),可能會發生異常並使容器處於非常糟糕的狀態。 –

+2

以這種方式定義IMO的可怕選擇...您可以創建自己的版本(不帶'&& std :: is_copy_constructible :: value'),這會導致編譯時錯誤。 – Joe

1

使用構造函數委託是實現此目的的一種方法。如果非委託構造函數(可能是沒有參數的構造函數,將您的成員設置爲默認值)已經完成並且構造函數委託拋出,則標準說您的本地狀態將被刪除。這樣你就不會泄漏。我今天在this talk瞭解到這一點。

順便說一下:STL尚未爲您設置什麼類型的容器?

+0

咕咕哈希表:) – Lazin

+0

從來沒有聽說過,但它聽起來很有趣,據[維基百科](http://en.wikipedia.org/wiki/Cuckoo_hashing)解釋它^^ – HaMster