标记可能导致构造返回对象异常的函数 `noexcept`

Per*_*-lk 21 c++ exception language-lawyer c++17 c++20

考虑这个函数:

std::vector<unsigned> copy(std::vector<unsigned> const& v) noexcept
{ return v; }

int main()
{
   try {
       (void)copy({1, 2, 3});
   } catch(...) {}
}

Run Code Online (Sandbox Code Playgroud)

返回对象的副本构造可能会抛出。在这种情况下,异常是否会传播给调用者(即它被认为发生在main),从而在处理catch(...)程序中进行处理?或者异常会遇到noexcept并导致调用std::terminate()

C++17/C++20 中关于生命周期规则的变化(标准化 RVO、临时物化、隐式对象创建等)是否相对于标准的先前版本改变了这方面的一些规则?

Sto*_*ica 15

C++17 有一个措辞更改,增加了围绕 return 语句的顺序。添加了以下段落。

[stmt.return]

3调用结果的复制初始化在由 return 语句的操作数建立的完整表达式末尾的临时变量销毁之前进行排序,而返回语句的操作数又在局部变量([ stmt.jump]) 包含 return 语句的块。

结果对象在作用域中的局部变量被销毁之前被初始化。这意味着 throw 在函数的范围内。因此,此时抛出的任何异常都不在调用方。

因此,将函数标记为noexcept将使程序终止。

RVO 不会改变这一点。它只影响结果对象在哪个存储中初始化,但初始化本身仍然是函数执行的一部分。

  • 我也相当确定所有这些也是 C++17 之前的预期行为,其中的措辞使其更加清晰。然而,我找不到最初在哪里读到这个意图。 (2认同)