【问题标题】:Throw a temporary argument passed by reference抛出一个通过引用传递的临时参数
【发布时间】:2015-03-05 10:38:30
【问题描述】:
inline void my_assert( bool cond, const std::exception &e = my_assert_failed() ) 
{ 
    if ( !cond ) 
      throw e;
}

该标准确保:

在函数调用 (5.2.2) 中与引用参数的临时绑定一直存在,直到包含调用的完整表达式完成为止。

对于抛出的临时对象:

只要有针对该异常的处理程序正在执行,临时性就会持续存在。

我能否推断出传递给my_assert 的临时变量在catch 块完成之前仍然存在?

【问题讨论】:

  • throw expression 执行其参数的副本,因此您不会抛出临时参数。
  • @user657267 这就是答案。

标签: c++ exception-handling


【解决方案1】:

来自 N4296(最终 C++14 之后的初稿)[15.1p3]:

抛出异常复制初始化(8.5,12.8)一个临时对象, 称为异常对象。临时值是左值并被使用 初始化在匹配处理程序 (15.3) 中声明的变量。

所以你不能假设你的临时“幸免于难”。如果抛出,std::exception 类型的异常对象的复制构造函数将以e 作为参数调用。当控制离开包含对my_assert 的调用的完整表达式时,e 绑定到的临时对象将被销毁(在正常返回之后或作为堆栈展开的一部分,因为您有条件地抛出异常)。

根据 [12.8p31.2],可以省略异常对象的复制构造,但这不是其中之一:

— 在 throw 表达式 (5.17) 中,当操作数是 a 的名称时 非易失性自动对象(不是函数或 catch 子句 参数),其范围不超出最内层的末尾 封闭的try-block(如果有的话),复制/移动操作 异常对象(15.1)的操作数可以省略 将自动对象直接构造到异常对象中

(强调我的)

【讨论】:

  • 很好的答案,准确而合理。编辑了问题以提高“幸存者”。
猜你喜欢
  • 2019-03-02
  • 2010-10-07
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 2011-08-21
  • 2014-05-05
  • 2017-09-25
  • 1970-01-01
相关资源
最近更新 更多