移动构造函数在下面显示的代码段中是否有任何特殊原因?

时间:2015-09-27 19:37:27

标签: c++ exception c++14 copy-elision

抛出对象#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'; } } 后,

gcc,clang和VS2015不会在下面的代码中忽略对move构造函数的调用。在我看来,§8.12[class.copy] / 31(N4140)的项目符号(31.2)中建立的条件得到满足。

a

请注意ActionBar ab = getActionBar(); ab.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#ff0000"))); 是左值,但根据§12.8/ 32,重载决策 首先执行选择复制的构造函数,就好像对象是由rvalue指定的一样。也就是说,对move构造函数的调用是可以的。如果删除上面的移动构造函数的定义,则调用复制构造函数,但同样,它不会被省略!

我理解标准没有规定复制省略,但我很想知道是否有任何特殊条件可以证明这一事实,上面提到的三个编译器在这个特定的例子中避免了这种优化。

gcc的示例输出,来自上面的链接:

  

g ++ -std = c ++ 14 -O2 -Wall -pedantic -pthread main.cpp&amp;&amp; ./a.out

     

默认ctor

     

移动ctor

     

析构函数

     

陷入

     

析构函数

1 个答案:

答案 0 :(得分:3)

根据12.8 [class.copy]第31段,第二个子弹可以省略抛出的局部变量的副本:

  

throw-expression 中,当操作数是非易失性自动对象(函数或catch子句参数除外)的名称时,其范围不会超出内   封闭 try-block (如果有的话),通过将自动对象直接构造到异常对象中,可以省略从操作数到异常对象(15.1)的复制/移动操作

似乎没有一个编译器使用这种优化。其中一个原因可能是因为努力更好地花在其他优化上,这根本不值得做。我认为标准中没有任何内容禁止这种优化。