我正在阅读std::move
,移动构造函数和移动赋值运算符。
说实话,我现在得到的只是困惑。现在我有一个班级:
class A{
public:
int key;
int value;
A(){key = 3; value = 4;}
//Simple move constructor
A(A&& B){ A.key = std::move(B.key);
A.value = std::move(B.value);}
};
B
是左值参考,为什么你可以将std::move
应用于ravlue参考的成员?B.key
和B.value
后,两者都已失效,但作为班级B
的对象的A
如何失效?A a(A())
,A()
显然是一个rvlaue,A()
可以std::move
移动,为什么会这样?同样,如果我有一个功能
int add(int && z){
int x = std:move(z);
int y = std:move(z);
return x+y;
}
如果我致电add(5)
该怎么办?5
如何移动?为什么?
请注意,z
已被移动两次,在第一次移动z
后,它已被无效,您又如何移动它?
foo (T && Z )
(T
时,Z
可以是任何内容),在定义的正文中为什么我应该使用std::move(Z)
Z
已经通过右值引用传递,何时应该使用std::move
? 答案 0 :(得分:11)
你必须明白std::move
不会移动任何东西,但是“标记”它的参数是一个右值引用。从技术上讲,它将类型转换为右值引用。然后,rvalue引用它被相应的移动构造函数或移动赋值运算符移动。对于仅包含具有普通移动ctors /赋值运算符的成员的对象,移动ctor /赋值运算符是微不足道的,只需复制。通常,对象的move ctor / assignment运算符调用其所有成员的move ctor / assignment运算符。
所以,每当你写
int x = 10; int y = std::move(x);
在作业y = std::move(x)
的右侧,您有一个类型为int&&
的右值引用。但是,int
没有非平凡的移动ctor,并且rvalue只是复制到y
,x
中没有任何更改。
另一方面,
string s = "some string"; string moved_s = std::move(s); // here we tell the compiler that we can "steal" the resource of s
是不同的。 moved_s
的移动构造函数启动,并且“窃取”(即交换内部指针等)s
的资源,因为后者是右值引用。最后,s
将不包含任何元素。
答案 1 :(得分:1)
B
是对象的名称。绑定引用后,它会命名一个对象。区别"右值参考","左值参考"和"命名对象"仅适用于在你走到这一步之前如何绑定名称。 B.key
是对象中变量的名称,该变量作为此函数调用的参数提供。
行A.key = std::move(B.key)
调用int
的内置赋值定义(这是一个简单的赋值,而不是函数调用),它只是一个副本。所以B.key
保留了它的价值。
要A(B())
进行编译,B
必须是您尚未定义的类型名称。 (您的意思是A(A())
吗?如果是,那么答案是"是")。
见2
当您想要离开std::move(Z.foo)
而不是从Z.foo
复制时,请使用Z.foo
。