我很感兴趣这是否是由标准强制执行的,以及是否被某些编译器所违反。我的观察是:
实际上,gcc 7.0甚至对此发出警告:
warning: throw will always call terminate() [-Wterminate]
表示NoExceptFunctionWithObj2()
。它使throw()的行为与noexcept(true)相同。 Test code:
#include <iostream>
#include <string>
#include <vector>
struct TestDataWithoutNoexcept {
TestDataWithoutNoexcept() {
std::cout << __FUNCTION__ << "\n";
}
~TestDataWithoutNoexcept() {
std::cout << __FUNCTION__ << "\n";
}
TestDataWithoutNoexcept(TestDataWithoutNoexcept const & rhs) {
std::cout << __FUNCTION__ << "\n";
}
TestDataWithoutNoexcept(TestDataWithoutNoexcept && rhs) {
std::cout << __FUNCTION__ << "\n";
}
TestDataWithoutNoexcept& operator=(TestDataWithoutNoexcept const& rhs) {
std::cout << __FUNCTION__ << "\n";
}
};
void NoExceptFunctionWithObj1() noexcept {
TestDataWithoutNoexcept test;
throw std::runtime_error("NoExceptFunctionWithObj1 ex.");
}
void NoExceptFunctionWithObj2() throw() {
TestDataWithoutNoexcept test;
throw std::runtime_error("NoExceptFunctionWithObj2 ex.");
}
int main()
{
// Now lets see whether stack is being unwound when exception is thrown in noexcept versus throw() function.
std::cout << "\n See how dtors are called in noexcept or throw() functions\n";
try {
//NoExceptFunctionWithObj1();
}
catch (std::runtime_error& ex) {
std::cout << ex.what();
}
try {
NoExceptFunctionWithObj2();
}
catch (std::runtime_error& ex) {
std::cout << "\nShouldn't this be shown? : " << ex.what();
}
}
最佳答案
是的,应该调用std::terminate
。标准的latest published draft表示:
15.4 [spec.except]第12段
这意味着throw()
严格等同于noexcept(true)
。 throw()
中不推荐使用C++17
。
15.5.1 [except.terminate]
不调用std::terminate
表示MSVC不兼容。
关于堆栈的处理,在您的示例中,编译器会进行所需的展开或不展开操作-这被指定为实现定义。
历史上(在C++ 11之前)在这种情况下必须进行堆栈展开。然而,事实证明,这种强制行为的运行时成本太高,并且它阻碍了编译器进行某些优化(即使在非异常情况下)。结果,编译器现在可以自由地将其省略。
经过@mike澄清后进行编辑。