0

我正在尝试测试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;
}

输出是:

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

环境:WIN8,Visual Studio 2012 Express

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

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

    B() 0
    B(常量 B&) 1
    ~B() 0
    ~B() 1

以下是我找到的参考资料:


编辑移动构造函数
应该是B(B&&)。问题是为什么调用构造函数而不是复制构造函数

4

1 回答 1

5

为什么这里不应用 RVO?

它不仅仅是执行优化。g++ 在使用-O2. 您应该在编译器上启用优化来测试这一点。但是,请注意,即使某些编译器可能会应用 RVO,它也不是强制性的,因此使用不同的编译器可能会看到不同的结果。

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

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

如果我删除 B(const B&&),则调用 B(const B&)。诡异的!

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

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

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

否则,您最终只会执行与复制构造函数中相同的操作。

于 2013-06-25T02:43:13.977 回答