Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ catch语句中是否会出现复制省略?_C++_Exception_Optimization_Copy Elision - Fatal编程技术网

C++ catch语句中是否会出现复制省略?

C++ catch语句中是否会出现复制省略?,c++,exception,optimization,copy-elision,C++,Exception,Optimization,Copy Elision,考虑一个具有副作用的复制构造函数的异常类 编译器是否可以跳过在此处调用复制构造函数: try { throw ugly_exception(); } catch(ugly_exception) // ignoring the exception, so I'm not naming it { } 那么这个呢: try { something_that_throws_ugly_exception(); } catch(ugly_exception) // ignoring the

考虑一个具有副作用的复制构造函数的异常类

编译器是否可以跳过在此处调用复制构造函数:

try {
    throw ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }
那么这个呢:

try {
    something_that_throws_ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }

(是的,我知道这一切都很丑陋,这是受启发的)

是的。如果
catch
通过引用捕获异常,那么就不会有复制(好的,这是根据定义)

但我认为这不是你的问题,我相信你写的代码是故意写的,没有提到参考。如果是这样,那么是的,即使在这种情况下,副本也可以省略。实际上,
catch
中变量的初始化在理论上是直接初始化。在可能的情况下,编译器可以省略直接初始化中的复制

C++03§8.5/14内容如下:

[…]在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除这种直接初始化中固有的复制


是的,在投掷和接球时都可以省略。对于捕获,只有当catch子句中指定的类型与异常对象的类型相同(cv限定除外)时,才能省略它。有关更正式和详细的描述,请参见C++11 12.8/31

…这种省略复制/移动操作(称为复制省略)在以下情况下是允许的(可以组合使用以消除多个副本):

  • 在抛出表达式中,当操作数是一个非易失性自动对象(函数或catch子句参数除外)的名称,该对象的作用域不超出最里面的封闭try块(如果有)的结尾时,从操作数到异常对象的复制/移动操作(15.1)可以通过将自动对象直接构造到异常对象中来省略

  • 当异常处理程序的异常声明(第15条)声明了与异常对象(15.1)相同类型的对象(cv限定除外)时,如果程序的含义除了执行异常声明声明所声明对象的构造函数和析构函数外没有改变,则可以通过将异常声明视为异常对象的别名来省略复制/移动操作

我认为这是明确允许的。对于C++03,15.1/3表示:

抛出表达式初始化临时对象,称为 异常对象

12/15说:

当尚未绑定到引用的临时类对象 (12.2)将复制到具有相同cv的类对象 类型,则可以通过构造节拍来省略复制操作- 将对象直接放入省略副本的目标中

因此,标准将保存飞行中异常的秘密隐藏位置定义为临时性的,因此对于副本省略是有效的

编辑:哎呀,我现在已经读了更多。15.1/5:

如果临时对象的使用可以消除而不改变 程序的含义,但构造函数的执行除外 和与临时对象的使用相关联的析构函数 (12.2),则可以直接初始化处理程序中的异常 使用throw表达式的参数

没有变得更清楚


是否真的会。。。如果catch子句要重新引发异常(包括它是否调用了可能会这样做的不可见代码),那么实现需要“临时对象调用异常对象”仍然存在。因此,可能会有一些限制,当复制省略是可能的。显然,空catch子句不能重新引发它。

这里没有引用,只考虑按值捕获时的复制省略。@Matthieu:我的答案大部分都提到了这一点。我想你只读了第一句话?关于标准引语:不清楚它是涉及一般的复制省略还是只涉及
catch
,你能准确地说吗?我没有只读第一句话,其余的答案其实很有趣。。。但是为什么要从OP没有问的东西开始呢?@Matthieu:可能是他想避免抄袭,但不知道怎么做,这就是我写第一句的原因有趣的是,虽然引文很窄。。。所以很难确定它是否真的指的是这种特殊的情况。@Mattieu:我有点懒于添加所有相关的引用,不管怎样,这里就是。谢谢这些毫无疑问的引用:)