更新时间: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.