我正在尝试测试 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;)。 提出了两个问题:
如果我删除 B(const B&amp;&amp;),则会调用 B(const B&amp;)。奇怪的输出:
B()0
B(const B&amp;)1
~B()0
~B()1
以下是我发现的参考资料:
修改:
移动构造函数应为 B(B&amp;&amp;)。这就是移动构造函数被称为复制构造函数的原因。
答案 0 :(得分:5)
为什么不在这里应用RVO?
这不仅仅是执行优化。使用-O2
时,g ++会在这里使用RVO。您应该在编译器上启用优化以对其进行测试。但请注意,即使某些编译器可能会应用RVO,也不是必需的,因此使用不同的编译器可能会看到不同的结果。
为什么不调用移动构造函数:B(const B&amp;)?
这是一个复制构造函数。它正在调用移动构造函数,这是一个更好的匹配。
如果我删除B(const B&amp;&amp;),则调用B(const B&amp;)。怪异!
不,这并不奇怪。如果定义了复制构造函数,则编译器不会隐式定义移动构造函数。因此,编译器正在选择复制构造函数,因为没有可用的移动构造函数。
请注意,您的移动构造函数应采用非常量右值引用:
B(B&& b) {
// ...
}
否则,你最终会像在复制构造函数中那样做。