如果我有一个e
类型的对象Error
来实现一个移动构造函数,那么抛出std::move( e )
会使用Error
的移动构造函数来复制“{{1}那么它是否避免制作对象的实际副本?所以,如果我有
e
是否会调用Error e;
throw std::move( e );
的复制构造函数?当你的移动构造函数是Error
(应该是)时,这是有意义的,但你的复制构造函数不是。
答案 0 :(得分:9)
§15.1[except.throw]:
抛出异常复制初始化(8.5,12.8)临时对象, 称为异常对象。该 temporary是一个左值,用于初始化匹配处理程序中指定的变量。
- 醇>
当抛出的对象是类对象时,即使复制/移动操作被省略,也应该可以访问为复制初始化和析构函数选择的构造函数(12.8)。
§8.5[dcl.init]:
- 醇>
以
形式出现的初始化
T x = a;
,以及参数传递,函数返回,抛出异常(15.1),处理异常 (15.3),聚合成员初始化(8.5.1)称为复制初始化。 [注意:复制初始化可以调用移动(12.8)。 - 后注]
§12.8[class.copy]:
- 当满足或将满足复制操作的省略标准时,除了源的事实 object是一个函数参数,要复制的对象由左值,重载决策指定 选择首先执行复制的构造函数就好像对象是由右值指定。
醇>
上述复制省略标准包括以下内容(§12.8[class.copy] / p31):
- 在 throw-expression 中,当操作数是非易失性自动对象的名称时(除了 function或catch-clause参数),其范围不超出最内层的末尾 封闭 try-block (如果有的话),从操作数到异常的复制/移动操作 通过将自动对象直接构造到异常对象
中,可以省略object(15.1)
异常的复制初始化可以调用move-constructor来构造实际的异常对象(即使std::move(e)
表达式中没有显式调用throw
),也不会调用其匹配的处理程序(如果试图被价值所吸引。)