簡體   English   中英

可能std :: vector中的元素有拋出析構函數嗎?

[英]May the elements in a std::vector have a throwing destructor?

當我查看cppreference上的Container需求時,它將Destructible列為value_type一個要求。 這似乎意味着容器元素的析構函數可能不會拋出。

我無法在C ++ 14標准中找到這個要求的引用(沒有查看舊版本)。 我唯一能找到的是value_type必須是Erasable ,這並不意味着任何異常安全。

所以我的問題是, std::vector的元素可能有拋出析構函數嗎? 如果沒有,標准中的哪個部分禁止它?


PS:別擔心,我不打算用拋出析構函數創建類型。 我只是編寫一個符合標准的實現,並試圖獲得異常安全權。

N4140 [res.on.functions] / 2州:

特別是,在以下情況下,效果未定義:

(2.1) - 對於替換函數(18.6.1),如果安裝的替換函數沒有實現適用的必需行為的語義:段落。

(2.2) - 對於處理函數(18.6.2.3,18.8.3.1,D.11.1),如果安裝的處理函數沒有實現適用的必需行為的語義:段落

(2.3) - 對於在實例化模板組件時用作模板參數的類型,如果對該類型的操作沒有實現適用的Requirements子句的語義(17.6.3.5,23.2,24.2,26.2)。 除非另有說明,否則對此類型的操作可以通過拋出異常來報告失敗。

(2.4) - 如果任何替換函數或處理函數或析構函數通過異常退出,除非在適用的必需行為:段落中明確允許。

(2.5) - 如果在實例化模板組件時使用不完整類型(3.9)作為模板參數,除非特別允許該組件。

這有點模糊,但在整個庫條款中節省了大量空間,否則會浪費在“ T必須符合可破壞要求”語句上。

值得注意的是,這並不意味着std::vector元素不能有拋出析構函數; 它只意味着當從標准庫調用時,所述析構函數必須永遠不會拋出。 所以例如這個程序符合:

#include <vector>

struct A {
  bool throw_an_int = false;
  ~A() noexcept(false) {
    if (throw_an_int) throw 42;
  }
};

int main() {
  try {
    A a; 
    a.throw_an_int = true;
    std::vector<A> lots_of_As(42);
  } catch(int&) {}
}

是。 標准在一般要求中說明了這一點:

[C++11: §23.2.1/10]:

除非另有規定(見23.2.4.1,23.2.5.1,23.3.3.4和23.3.6.5),本條款中定義的所有容器類型均滿足以下附加要求:

- 沒有erase(),clear(),pop_back()或pop_front()函數拋出異常。

使用clear函數作為示例(由於它不是一般要求的例外),它具有以下要求:

破壞a中的所有元素。 使引用a元素的所有引用,指針和迭代器無效並且可能使過去的迭代器無效。 發布: a.empty()返回true

這意味着它基本上在所有元素上調用std::allocator_traits<Alloc>::destroy 如果a.destroy(t)不可用,則委托給t->~T() 然而,這隱含地保證a.destroy(t)t->~T()都不應該拋出,因為它會違反clear的強烈noexcept規范:

// § 23.3.6.1
void clear() noexcept;

因此,通過演繹,我們可以斷言析構函數可以拋出但是必須通過某種機制來抑制它們,例如將它們包裝在try-catch塊中。

†:經過進一步檢查,似乎析構函數可以拋出但是必須如下面的評論中所述那樣禁止例外。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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