C++11 复制省略号和异常(catch 参数)

标签 c++ c++11 exception copy-constructor copy-elision

在代码审查之后,我们在 try/catch block 中遇到了复制 elison 的问题。 阅读此页面后: cpp reference guide特别是这一段:

When handling an exception, if the argument of the catch clause is of the same type (ignoring top-level cv-qualification) as the exception object thrown, the copy is omitted and the body of the catch clause accesses the exception object directly, as if caught by reference

我认为 catch 中参数的复制省略会自动执行,但其中一位审阅者运行了一个简单的测试,表明编译器没有执行复制省略:

#include <iostream>

class A
{
public:
   A(){}
   A(const A&){
    std::cout<<"COPY CONSTRUCTOR\n";
   }
};

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

是测试用例无效还是我对copy elision的理解有误? 非常感谢您的帮助

最佳答案

When handling an exception, if the argument of the catch clause is of the same type (ignoring top-level cv-qualification) as the exception object thrown, the copy is omitted ...

cppreference 上的措辞过于强烈。这是一份允许复制省略的案例列表。那应该是:“拷贝可以省略”。

看起来编译器没有执行复制省略,即使它被允许。


标准(草案)相关引述:

[class.copy.elision] / 1

... This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

[class.copy.elision] / 1.3

when the exception-declaration of an exception handler (Clause [except]) declares an object of the same type (except for cv-qualification) as the exception object, the copy operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration. [ Note: There cannot be a move from the exception object because it is always an lvalue.  — end note ]

关于C++11 复制省略号和异常(catch 参数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42652965/

相关文章:

c++ - "inline"功能的用处

C++:如果类没有成员函数,如何创建抽象基类?

c++ - Cereal Polymorphic Serialization 找不到序列化函数

c++ - 测量嵌入式系统代码执行时间的最佳 C++11 方法

c++ - 在条件变量上发出信号之前是否必须锁定互斥锁?

java - ClassNotFoundException com.mysql.jdbc.Driver

c++ - 命名结构与未命名结构的类型别名

C++ 11初始化程序具有模棱两可的函数id表达式?

c# - 未处理的异常未被 `Application.ThreadException` 捕获?

c# - 如何优雅地处理ViewState错误?