【发布时间】:2014-02-17 13:45:09
【问题描述】:
最近我试图在noexcept 异常规范中回答我认为是simple question 的问题。结果发现自己对noexcept的基本理解是错误的。
在阅读the current draft standard 以纠正我的误解时,我发现自己问了一些关于noexcept 的问题,而here 没有得到回答。
- 是否应该将
noexcept视为一种安全保证,即调用该函数时不仅不会抛出状态,而且不会破坏状态? - 假设 (1.) 为假:使用
noexcept作为可移植的 FailFast 来终止应用程序而不进行清理以防止损坏保存状态是否正确?
对 (2.) 的澄清: 目的只是为了防止从noexcept 进一步向上堆栈调用析构函数,而不是防止在其中展开。这是基于以下假设:这是一个完美的 RAII 环境,堆栈上的析构函数可以将全局状态刷新到持久性,从而破坏它。
不执行展开的示例:
#include <iostream>
#include <exception>
namespace{
struct foo{
void change_state() noexcept
{
// change state and fail
throw std::exception();
}
~foo(){
std::cout << "Destructor called, saved state corrupted!" <<std::endl;
}
};
}
int main(){
::std::set_terminate([](){
std::cout<< "Terminate called" <<std::endl;
});
foo f;
f.change_state();
return 0;
}
【问题讨论】:
-
据我所知
noexcept:即使这件事抛出我也不想知道。所以它并不真正适用于“安全”或“正确性”,它通过防止抛出异常来工作,这样你的程序就不会因此而结束。 -
如果异常到达标记为
noexcept的函数的最外层块,则调用std::terminate。它根本不抑制异常。它提供了一个障碍,可能不会引发异常 -
我之前写的是关于runtime,
noexcept在编译时工作,所以它是给编译器的一个提示,编译器会评估你的程序,如果有机会抛出的东西,你有机会在 runtime 之前纠正这个问题,因为noexcept运算符将在 compile time 失败。它在某些方面像type traits一样工作,你定义一个需要评估为true的属性,如果不是,编译器会警告你,如果测试通过你知道在 runtime 你将拥有您在traits条件中定义的类型。noexcept也是如此。 -
我认为没有理由相信 1)(函数总是会破坏状态,即使没有例外),但我会说 2)是正确的。
-
@user2485710 我认为您无法理解
noexcept请阅读上述问题中的链接标准。这绝对不是noexcept所做的。拥有一个标记为noexcept且其中包含throw语句的函数是完全合法的,甚至没有catch表示抛出。然而,结果将是调用std::terminate。
标签: c++ language-lawyer noexcept