gcc, clang 和 VS2015 在抛出 object 之后,不会在下面的代码中省略对 move 构造函数的调用a
。在我看来,§8.12[class.copy]/31 (N4140) 的要点 (31.2) 中建立的条件得到满足。
#include <iostream>
struct A
{
A() { std::cout << "Default ctor " << '\n'; }
A(const A& a) { std::cout << "Copy ctor" << '\n'; }
A(A&& a) { std::cout << "Move ctor" << '\n'; }
~A() { std::cout << "Destructor " << '\n'; }
};
int main()
{
try
{
A a;
throw a;
}
catch(A& a) { std::cout << "Caught" << '\n'; }
}
请注意,这a
是一个左值,但根据第 12.8/32 节,首先执行为复制选择构造函数的重载决策,就好像对象是由右值指定的一样。也就是说,调用移动构造函数是可以的。如果您删除上面移动构造函数的定义,则会调用复制构造函数,但同样,它不会被忽略!
我知道标准没有强制要求复制省略,但我很想知道是否有任何特殊条件可以证明上述三个编译器在这个特定示例中避免了这种优化这一事实。
gcc 的示例输出,来自上面的链接:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
默认 ctor
移动 ctor
析构函数
抓住
析构函数