【发布时间】:2013-07-29 03:48:03
【问题描述】:
在 C++11 中已弃用:
void foo() throw();
替换为
void foo() noexcept;
在this article 中解释了这样做的原因(其中归结为同一件事)是因为
C++ 异常规范是在运行时而不是在编译时检查的,因此它们不提供程序员保证所有异常都已处理。
虽然这对我来说确实有意义,但我不明白为什么首先动态检查 throw(),或者为什么 noexcept 除了调用 std::terminate 而不是正常的堆栈展开之外不提供异常保证(这并不是 IMO 的可靠保证)。
难道不能在编译期间检查是否抛出异常,如果发生这种情况,编译会失败吗?在我看来,基本上有三种情况:
void foo() noexcept
{
// 1. Trivial case
throw myexcept();
// 2. Try-catch case
// Necessary to check whether myexcept is derived
// from exception
try
{
throw myexcept();
}
catch(exception const & e)
{}
// 3. Nested function call
// Recursion necessary
bar();
}
在 C++ 中为每种类型都实例化模板后,编译应用程序无论如何都要花很长时间 - 那么为什么不更改 noexcept 以强制编译器检查是否在编译期间抛出异常?
我看到的唯一困难是函数可能会或可能不会抛出取决于运行时状态 - 但在我看来,无论如何不应允许该函数自称noexcept。
我是否遗漏了什么,或者是为了不进一步增加编译时间,还是为了让编译器开发人员轻松一些?
【问题讨论】:
-
编译器无法知道您在函数中调用的库函数是否会引发异常。
-
throw()是编译器向您提供的保证。noexcept是您对编译器的保证。 -
@PetrBudnik:当然有,任何未标记为
noexcept的函数都可能是throw。 -
@MatthieuM。甚至不进入动态加载,您是否建议 C++11 编译器应该拒绝编译
void foo() noexcept( true ) { bar(); },其中bar()来自在引入noexcept关键字之前创建的库? -
@KerrekSB:您的意思是编译器通过调用 terminate() 向您提供beat you senseless 的保证,如果仍然抛出异常(并且通过不展开堆栈来违反所有 RAII 期望)?跨度>