【发布时间】:2011-11-09 13:50:44
【问题描述】:
调用std::vector<T>::clear() 是否有机会引发异常?
【问题讨论】:
-
很好的问题,暴露了很多人不知道正确答案!
-
@VJo:在您删除答案之前,我没有机会回复。 “这使得只能从一个对象抛出异常”:怎么会?
调用std::vector<T>::clear() 是否有机会引发异常?
【问题讨论】:
没有。
[2003: 21.2.1/11 | n3290: 21.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()函数抛出异常。 [..]
在 C++11 中,std::vector<T>::clear() 标记为 noexcept ([n3290: 23.3.6/1])。
任何脱离~T 的异常都可以被实现捕获,因此clear() 本身可能不会抛出任何东西。如果它们不是,并且确实如此,则异常是“意外的”并终止进程而不是传播:
struct T {
~T() { throw "lol"; }
};
int main() {
try {
vector<T> v{T()};
v.clear();
}
catch (...) {
cout << "caught";
}
}
// Output: "terminated by exception: lol" (GCC 4.7.0 20111108)
[n3290: 15.5.1]:在某些情况下必须进行异常处理 放弃了不太微妙的错误处理技术。 [..] - 当。。。的时候 搜索处理程序 (15.3) 遇到 a 的最外层块 no-except-specification 的函数不允许 例外 (15.4) [..]
【讨论】:
vector 的元素类型的要求之一是它的析构函数不会抛出。如果您违反要求,则行为未定义,因此实现无需捕获来自~T() 的异常。
.clear 是noexcept 以添加额外的诊断安全层。
是的,如果T的析构函数抛出,否则不会。
更新: 看来我错了;在那种情况下它只会崩溃
【讨论】:
是与否
是的:
clear 最终调用delete[] 运算符,这涉及调用数组(如果有的话)和free 内存中所有对象的析构函数。
析构函数最终可能会抛出异常。
在异常情况下(例如堆损坏等),内存释放也可能失败
没有:
抛出异常是析构函数受到批评并且大多数情况下不会发生(至少在标准库中)。除了在堆栈展开期间析构函数抛出的异常(由另一个异常引起)可能无法处理之外,析构函数中的异常存在逻辑问题。
释放内存的错误通常是由堆损坏或其他不可恢复的问题引起的。反正程序的命运就是死,不管有没有例外
【讨论】:
clear(实际上没有std::vector的函数)永远不会调用delete[]。