【发布时间】:2017-10-10 13:01:09
【问题描述】:
我正在尝试使用以下代码来理解移动语义。
#include <iostream>
#include <utility>
using namespace std;
class A
{
public:
int a;
A():a{1}{}
A(A&& rref):a{rref.a}{cout<<"move constructor called"<<endl;}
A(const A& ref):a{ref.a}{cout<<"copy constructor"<<endl;}
};
int main(){
A original; // original object
cout<<"original.a = "<<original.a<< "| address original.a="<< &(original.a)<<endl;
A movedto (std::move(original)); // calls A(A&&)
cout<<"original.a = "<<original.a<< "| address original.a"<< &(original.a)<<endl;
cout<<"movedto.a = "<<movedto.a<<"| address movedto.a"<< &(movedto.a)<<endl;
return 0;
}
给出以下输出
original.a = 1| address original.a=0x7fff1611b6d0
move constructor called
original.a = 1| address original.a0x7fff1611b6d0
movedto.a = 1| address movedto.a0x7fff1611b6e0
可以看出original.a和movedto.a的地址不同,所以a成员在A(A&& rref):a{rref.a}进行了复制操作。
我知道 move 对于内置类型会降级为 copy。我的问题是如果我想劫持(而不是复制)这个类的一个实例,我该怎么办。假设我有 100 个(而不是只有一个)内置类型的成员,这会使复制变得昂贵。
一种明显的方法是将对象存储在堆上并使用引用语义来传递它。但是希望保留值语义并且仍然能够规避复制。
【问题讨论】:
-
复制 100 个
ints 仍然不贵。但是您可以使用std::vector<int>成员并移动它。它会为你处理一切。 -
两个问题:1)
std::vector<T>是否具有值语义? 2)如果1的答案是肯定的,vector<T>是做什么的? -
a{rref.a}应该是a{std::move(rref.a)}才能实际移动a(尽管它仍然会复制,因为它与int相同)。 -
您在这里使用内置类型这一事实无关紧要。不管你做什么类型
a、original.a和movedto.a仍然会有不同的地址。 -
不,@NathanOliver 是正确的,
rref.a是左值,因为rref是左值(命名为右值引用)。如果您希望它成为 xvalue,则需要std::move(rref.a)。或者,如果你已经完成了std::move(rref).a,那么它也可以工作,因为.运算符将从右值提供一个右值。
标签: c++ move-semantics