【发布时间】:2017-03-07 16:07:53
【问题描述】:
在对代码进行审查后,我们在 try/catch 块中遇到了复制 elison 的问题。 阅读此页面后: cpp reference guide 尤其是这一段:
处理异常时,如果catch子句的参数与抛出的异常对象属于同一类型(忽略顶级cv-qualification),则省略副本,catch子句的主体访问异常对象直接,好像被引用抓住了
我认为 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
是测试用例无效还是我对复制省略的理解有误? 非常感谢您的帮助
【问题讨论】:
-
引用确实声明:在以下情况下,编译器可以省略类对象的复制和移动(C++11 起)构造函数,即使复制/移动(由于 C++11) 构造函数和析构函数具有可观察到的副作用。。仅仅因为它被允许并不意味着它会发生。
-
我不太关心副本(无论如何这是一种特殊情况),但
catch(A a)只是 看起来 错误,因为通过 const 引用进行捕获已经如此牢固地确立在 C++ 的世界里。更不用说对象切片的危险了。 -
权威引用的 std 子句是 eel.is/c++draft/class.copy#elision-1.3
标签: c++ c++11 exception copy-constructor copy-elision