可能std::向量中的元素具有抛出的析构函数
May the elements in a std::vector have a throwing destructor?
当我查看cppreference上的Container
需求时,它将Destructible
列为value_type
的需求。这似乎意味着容器元素的析构函数可能不会抛出。
我在C++14标准中找不到这一要求的引文(没有在旧版本中找到)。我唯一能找到的是value_type
必须是Erasable
,这并不意味着任何异常安全性。
所以我的问题是,std::vector
中的元素可能有抛出析构函数吗?如果没有,标准中的哪一节禁止?
附言:别担心,我不打算创建带有抛出析构函数的类型。我只是在写一个符合标准的实现,并试图获得正确的异常安全性。
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)——对于在实例化模板组件时用作模板参数的类型,如果对该类型的操作没有实现适用的"要求"子条款(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块中。
&匕首;:经过进一步检查,析构函数似乎可以抛出,但必须抑制异常,如下面的注释所述。
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 带有未解析外部元素的C++虚拟析构函数
- 析构函数删除错误的元素
- set.clear() 在删除元素之前调用所包含元素的析构函数
- boost::lockfree-为排队的元素调用析构函数
- 父类析构函数删除具有外部启动元素的子类
- 在元素自己的析构函数中擦除指向静态向量中元素的指针
- 可能std::向量中的元素具有抛出的析构函数
- Delete[]未调用元素析构函数
- 从unordered_map中删除元素而不调用析构函数
- std::list 的擦除成员函数是否为所有存储的元素调用析构函数?
- 从向量中移除元素时,析构函数调用了两次