C 11复制Elison和异常(捕获论点)

C++11 copy elison and exception (catch argument)

本文关键字:异常 复制 Elison      更新时间:2023-10-16

在代码审核之后,我们在try/Catch Block中与Cople Elison有一个问题。阅读此页面后:CPP参考指南,尤其是本段:

处理异常时,如果捕获子句的参数是相同类型的(忽略顶级CV-qualifience),则丢弃了副本,并且捕获子句的正文访问了异常对象直接,好像被参考

捕获

我认为,将自动执行捕获论点的复制责任,但其中一位审稿人进行了一个简单的测试,显示编译器未执行复制elision:

#include <iostream>
class A
{
public:
   A(){}
   A(const A&){
    std::cout<<"COPY CONSTRUCTORn";
   }
};
int main()
{
    try {
       throw A{};
    } catch(A a) {
       throw a;
    }
    return 0;
 }

编译时:

g++ a.cpp -std=c++11 -O3

我得到以下输出

COPY CONSTRUCTOR
COPY CONSTRUCTOR
terminate called after throwing an instance of 'A'
Aborted (core dumped)

我期望的输出类似(抛出异常时只有一个复制构造器的调用):

COPY CONSTRUCTOR
terminate called after throwing an instance of 'A'
Aborted (core dumped)

该测试已在Linux Ubuntu 16.04下进行,具有G 版本:

 g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

测试案例是无效的还是我对副本剥离的理解是错误的?非常感谢您的帮助

处理异常时,如果捕获子句的参数为相同的类型(忽略顶级cv-qualification),则省略了副本,省略了副本...

cppreference上的措辞过于强烈。这是复制ELISION为允许的情况的列表。应该阅读:&quot 可以被省略

看来,即使允许编译器执行复制责任。


标准(草稿)的相关报价:

[class.copy.elision]/1

...在以下情况下允许使用复制/移动操作(称为复制责任)(可以合并以消除多个副本):

[class.copy.elision]/1.3

当异常处理程序的异常解释(条款[异常])声明相同类型的对象(CV-qualification除外)为异常对象,可以通过将副本操作视为例外 - 范围来省略复制操作如果程序的含义不变,则异常对象的别名除非执行构造函数和驱动器,否则由异常解释声明的对象的构造函数和破坏者。[注意:由于它始终是lvalue,因此不能从异常对象转移。 - 终注]