使用move构造函数抛出异常?(C++)

spe*_*ber 10 c++ exception move

如果我有一个实现移动构造函数e的类型的对象Error,将抛出std::move( e )使用移动构造函数Error来"复制" e,那么它是否避免制作对象的实际副本?所以,如果我有

Error e;

throw std::move( e );
Run Code Online (Sandbox Code Playgroud)

是否Error会调用复制构造函数?当你的移动构造函数noexcept(应该是)时,这是有意义的,但你的复制构造函数不是.

Pio*_*cki 10

§15.1[except.throw]:

  1. 抛出异常copy-initializes(8.5,12.8)一个临时对象,称为异常对象.临时值是一个左值,用于初始化匹配处理程序中指定的变量.

  2. 当抛出的对象是类对象时,即使复制/移动操作被省略,也应该可以访问为复制初始化和析构函数选择的构造函数(12.8).

§8.5[dcl.init]:

  1. 在表单中发生的初始化

    T x = a;

,以及在参数传递,函数返回,抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.5.1)被称为复制初始化.[注意:复制初始化可以调用移动(12.8). - 尾注]

§12.8[class.copy]:

  1. 当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.

上述复制省略标准包括以下内容(§12.8[class.copy]/p31):

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

异常的复制初始化可以调用move-constructor来构造实际的异常对象(即使std::move(e)未在throw表达式中显式调用),但不是它的匹配处理程序(如果试图被值捕获).