【问题标题】:Will an exception thrown from a noexcept function parameter's constructor immediately result in a call to std::terminate()?从 noexcept 函数参数的构造函数抛出的异常会立即导致对 std::terminate() 的调用吗?
【发布时间】:2016-07-13 13:21:45
【问题描述】:

给定以下类声明:

class phone_number
{
public:
    explicit phone_number( std::string number ) noexcept( std::is_nothrow_move_constructible< std::string >::value );
}

phone_number::phone_number( std::string number ) noexcept( std::is_nothrow_move_constructible< std::string >::value )
    : m_originalNumber{ std::move( number ) }
{

}

如果字符串构造函数抛出异常,以下代码行是否会由于 noexcept 规范而立即调用std::terminate()

const phone_number phone("(123) 456-7890");

【问题讨论】:

  • const char * 的字符串构造函数由 you 调用,而不是由 phone_number 构造函数调用。移动构造函数不会抛出。

标签: c++ c++11 exception noexcept


【解决方案1】:

由于在调用函数之前评估所有参数,因此由参数的构造函数发出的异常不会违反函数本身的noexcept 契约。

为了确认这一点,这是我尝试过的,近似于您的示例:

class A
{
public:
    A(const char *)
    {
        throw std::exception();
    }
};

void f(A a) noexcept
{

}

int main()
{   
    try
    {
        f("hello");
    }
    catch(std::exception&)
    {
        cerr<< "Fizz..." << endl;
    }
    return 0;
}

不出所料,输出为Fizz...,程序正常退出。

【讨论】:

    【解决方案2】:

    C++有两种异常规范:

    动态异常规范(已弃用)

    看起来像这样:

    void foo() throw(x, y, z)
    

    在这种情况下,如果在 foo 中引发了不在集合 x、y 或 z 中的异常,则调用 std::unexpected()。默认情况下,这将调用std::terminate(),但您可以通过设置自己的意外处理程序来进行干预,它甚至可能抛出 x、y 或 z 以允许程序继续运行。当然,从来没有人这样做过。

    noexcept 规范 (c++11 起)

    看起来像这样:

    void foo() noexcept; // same as noexcept(true)
    void foo() noexcept(true); // not allowed to throw exceptions
    void foo() noexcept(false); // allowed to throw exceptions
    

    这是有趣的地方,因为如果foo() noexcept(true) 确实抛出了异常,则行为不同。标准要求应调用std::terminate()

    您没有机会捕获异常或以其他方式纠正这种情况。一个庄严的承诺已经做出并被打破 - 程序结束。

    来自 §15.4 [except.spec]

    10 每当抛出 E 类型的异常并且搜索处理程序 (15.3) 遇到最外层 具有不允许 E 的异常规范的函数块,则,

    (10.1) — 如果函数定义具有动态异常规范,则函数 std::unexpected() 是 称为(15.5.2),

    (10.2) — 否则,调用函数 std::terminate() (15.5.1)

    【讨论】:

      猜你喜欢
      • 2018-03-21
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多