【发布时间】:2014-08-06 06:15:37
【问题描述】:
They say Rvalues 的成员也是 Rvalues - 这很有意义。所以这要么是 VC++ 特有的错误,要么是我对 Rvalues 的理解中的错误。
拿这个玩具代码:
#include <vector>
#include <iostream>
using namespace std;
struct MyTypeInner
{
MyTypeInner() {};
~MyTypeInner() { cout << "mt2 dtor" << endl; }
MyTypeInner(const MyTypeInner& other) { cout << "mt2 copy ctor" << endl; }
MyTypeInner(MyTypeInner&& other) { cout << "mt2 move ctor" << endl; }
const MyTypeInner& operator = (const MyTypeInner& other)
{
cout << "mt2 copy =" << endl; return *this;
}
const MyTypeInner& operator = (MyTypeInner&& other)
{
cout << "mt2 move =" << endl; return *this;
}
};
struct MyTypeOuter
{
MyTypeInner mt2;
MyTypeOuter() {};
~MyTypeOuter() { cout << "mt1 dtor" << endl; }
MyTypeOuter(const MyTypeOuter& other) { cout << "mt1 copy ctor" << endl; mt2 = other.mt2; }
MyTypeOuter(MyTypeOuter&& other) { cout << "mt1 move ctor" << endl; mt2 = other.mt2; }
const MyTypeOuter& operator = (const MyTypeOuter& other)
{
cout << "mt1 copy =" << endl; mt2 = other.mt2; return *this;
}
const MyTypeOuter& operator = (MyTypeOuter&& other)
{
cout << "mt1 move =" << endl; mt2 = other.mt2; return *this;
}
};
MyTypeOuter func() { MyTypeOuter mt; return mt; }
int _tmain()
{
MyTypeOuter mt = func();
return 0;
}
此代码输出:
mt1 移动 ctor
mt2 复制 =
mt1 dtor
mt2 dtor
即MyTypeOuter的move ctor调用MyTypeInner的copy,而不是move。如果我将代码修改为:
MyTypeOuter(MyTypeOuter&& other)
{ cout << "mt1 move ctor" << endl; mt2 = std::move(other.mt2); }
输出如预期:
mt1 移动 ctor
mt2 移动 =
mt1 dtor
mt2 dtor
似乎 VC++(2010 和 2013)不尊重这部分标准。还是我错过了什么?
【问题讨论】:
-
您是否在编译时进行了全面优化?
-
没有。随着优化 RVO 的启动,整个移动语义逻辑就像碎肉一样。
-
您仍然必须在构造函数中使用
std::move(other),如果您要执行MyTypeInner mt = func().mt2;之类的操作,编译器只会将成员视为右值而不进行移动。 -
那么 rvalue-members 以什么方式本身是 rvalue 呢?我希望这个定义在这里准确地体现出来。在语句 mt2 = other.mt2 中,如果 rhs 确实是右值,则应调用 move 赋值。
-
@OfekShilon
other在该表达式中是左值,除非您移动它,请参阅this 问题。
标签: c++ visual-c++ c++11