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

Zac*_*ary 0 c++ copy-constructor rvo

我正在尝试测试RVO右值参考.这是代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

B() 0
B(const B&&) 2
~B() 0
~B() 2
Run Code Online (Sandbox Code Playgroud)

环境:WIN8,Visual Studio 2012 Express

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

  • 为什么RVO不适用于此?
  • 为什么调用复制构造函数:B(const B&)
  • 如果我删除B(const B &&),则调用B(const B&).奇怪的输出:

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

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


编辑:
移动构造函数应该B(B &&) .这就是移动构造函数被称为复制构造函数的原因.

mfo*_*ini 5

为什么RVO不适用于此?

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

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

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

如果我删除B(const B &&),则调用B(const B&).奇怪的!

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

请注意,您的移动构造函数应采用非const rvalue引用:

B(B&& b) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

  • @Zack:它甚至在[docs](http://msdn.microsoft.com/en-us/library/8f8h5cxt.aspx)中也这样说:`/ O1和/ O2也启用了命名返回值优化. (3认同)
  • @Zack我的观点是:启用优化. (2认同)