且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

抛出异常时不调用Move构造函数

更新时间:2022-05-31 07:52:32

这是一个MSVC bug。 from [except.throw]:

This is an MSVC bug. From [except.throw]:


抛出异常副本 - 初始化(8.5,12.8)临时对象,称为异常对象

这意味着我们:

ThrowMoveTest __exception_object = move(tmt1);

这应该肯定会调用move构造函数。

which should definitely call the move constructor.

请注意,这里的 move 是不必要的,也是有害的。 [class.copy]规定可以舍弃复制/移动构造

Note that the move here is unnecessary and also damaging. [class.copy] stipulates that copy/move construction can be elided


5.17),当操作数是一个非易失性自动对象(除
a函数或catch子句参数之外)的名称,该对象的范围不超过最内侧的
结束try-block如果有一个),从操作数到异常
对象(15.1)的复制/移动操作可以通过将自动对象直接构造为异常对象来省略

— in a throw-expression (5.17), when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

因此,简单地 throw tmt1; 会允许构建 tmt1 直接进入异常对象。虽然gcc和clang都不这样做。

So simply throw tmt1; would have allowed for tmt1 to be constructed directly into the exception object. Although neither gcc nor clang do this.

即使复制/移动没有消失:

And even if the copy/move is not elided:


满足复制/移动操作的精度的标准,但不是针对异常声明,并且要复制的
对象由lvalue [...]重载解析
指定以选择构造函数

When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue [...] overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

因此 throw tmt1; 仍然会移动 - 构造异常对象。

So throw tmt1; would still move-construct the exception object.