为什么RVO不能与移动构造函数一起使用?

时间:2013-06-25 02:38:50

标签: c++ copy-constructor rvo

我正在尝试测试 RVO rvalue 参考。这是代码:

#include <iostream>

using namespace std;

class B{
public:
    int i;

    B(){
        i = 0;
        cout << "B() " << i << endl;
    }

    B(const B& b){
        i = 1;
        cout << "B(const B&) " << i << endl;
    }

    B(const B&& b){//if remove this constructor, then call B(const B& b)
        i = 2;
        cout << "B(const B&&) " << i << endl;
    }

    ~B(){
        cout << "~B() " << i << endl;
    }
};

B f(){
    B b;
    return b;
}

int main(){

    B b = f();

    return 0;
}

输出结果为:

B() 0
B(const B&&) 2
~B() 0
~B() 2

环境:WIN8,Visual Studio 2012 Express

这意味着调用移动构造函数:B(const B&amp;&amp;)。 提出了两个问题:

  • 为什么 RVO 未在此处应用?
  • 为什么 NOT 调用复制构造函数:B(const B&amp;)
  • 如果我删除 B(const B&amp;&amp;),则会调用 B(const B&amp;)。奇怪的输出:

    B()0
    B(const B&amp;)1
    ~B()0
    ~B()1

以下是我发现的参考资料:


修改
移动构造函数应为 B(B&amp;&amp;)。这就是移动构造函数被称为复制构造函数的原因。

1 个答案:

答案 0 :(得分:5)

  

为什么不在这里应用RVO?

这不仅仅是执行优化。使用-O2时,g ++会在这里使用RVO。您应该在编译器上启用优化以对其进行测试。但请注意,即使某些编译器可能会应用RVO,也不是必需的,因此使用不同的编译器可能会看到不同的结果。

  

为什么不调用移动构造函数:B(const B&amp;)?

这是一个复制构造函数。它正在调用移动构造函数,这是一个更好的匹配。

  

如果我删除B(const B&amp;&amp;),则调用B(const B&amp;)。怪异!

不,这并不奇怪。如果定义了复制构造函数,则编译器不会隐式定义移动构造函数。因此,编译器正在选择复制构造函数,因为没有可用的移动构造函数。

请注意,您的移动构造函数应采用非常量右值引用:

B(B&& b) {
    // ...
}

否则,你最终会像在复制构造函数中那样做。