【问题标题】:Who manages the exception thrown by a copy constructor in parameters? [duplicate]谁管理参数中复制构造函数抛出的异常? [复制]
【发布时间】:2020-01-21 16:55:41
【问题描述】:

假设我有这个功能

void foo() noexcept
{
   // Safely noexcept code.
}

然后是这个类:

class Bar
{
   Bar(const Bar&) { ... } // Is not noexcept, so might throw
   // Non movable:
   Bar(Bar&&) = delete;
};

现在,我需要修改 foo() 以按值接收 Bar:

void foo(Bar bar) // noexcept?
{
   // Safely noexcept code
}

我假设 Bar 的副本是在调用 foo 之前完成的,所以 foo 的代码理论上仍然可以是 noexcept, 但我不确定在 C++ 级别是如何定义的。 foo 是否需要删除 noexcept 或者是在应对 Bar 时可能抛出的调用者? 它是否取决于调用模式(stdcall、farcall 等)或编译器? 更新:在其他问题中,我没有发现对调用约定的任何引用。这应该会对行为产生影响。我想。

【问题讨论】:

  • foo 可以保留noexcept。复制(如果有)发生在调用之前。
  • @jarod42 但这不取决于编译器的调用约定吗?

标签: c++ exception copy-constructor pass-by-value noexcept


【解决方案1】:

见 [expr.call]/4:

每个参数的初始化和销毁​​发生在上下文中 调用函数。 [ 示例: 在调用函数的调用点检查构造函数、转换函数或析构函数的访问。如果函数参数的构造函数或析构函数抛出异常,则在调用函数的范围内开始搜索处理程序;特别是,如果被调用的函数有一个 function-try-block(第 18 条)和一个可以处理异常的处理程序,则不考虑这个处理程序。 ——结束示例 ]

因此您仍然可以标记foo noexcept,即使bar 的初始化可能会抛出。调用函数不应该是noexcept。 (也就是说,除非您同意程序在发生异常时终止。)

【讨论】:

  • 返回值的初始化如何?
  • 我要再补充一点,即使默认参数的评估也发生在调用者上下文中
  • @DanielLangr 这应该作为一个新问题提出。
【解决方案2】:

参数的构造发生在调用者中;一旦所有参数都被构建/转换,函数就会被调用。

可能不太明显的是,在 C++ 中,即使是未传递参数的默认值表达式也会发生在调用者中:即

void foo(MyClass x=MyClass()) {
    ...
}

情况下的构造

foo();

在实际调用函数之前仍在调用者站点完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2014-08-02
    • 2019-07-11
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多