移动构造函数和std :: move混乱 [英] move constructor and std::move confusion
问题描述
我正在阅读 std::move
,移动构造函数并移动赋值操作员.
老实说,我现在所得到的只是混乱.现在我上了一堂课:
I am reading about the std::move
, move constructor and move assignment operator.
To be honest, all I got now is confusion. Now I have a class:
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
之后,它们都已失效,但是作为类A
的对象的B
如何失效? - 如果我有
A a(A())
,A()
显然是rvlaue,std::move
可以移动A()
怎么办?为什么? -
类似地,如果我有功能
- I thought
B
is an rvalue reference, why you can applystd::move
to an ravlue reference's member? - After
B.key
andB.value
have been moved, both have been invalidated, but howB
as an object of classA
gets invalidated? - What if I have
A a(A())
,A()
is apparently an rvlaue, canA()
be moved bystd::move
and why? Similarly, if I have a function
int add(int && z){
int x = std:move(z);
int y = std:move(z);
return x+y;
}
int add(int && z){
int x = std:move(z);
int y = std:move(z);
return x+y;
}
如果我呼叫add(5)
,怎么移动5
?为什么?
并注意z
已被移动两次,第一次z
被移动后,它已失效,如何再次移动它?
What if I call add(5)
, how can 5
be moved and why?
And notice that z
has been moved twice, after z
has been moved first time, it has been invalidated, how can you move it again?
- 在定义
foo (T && Z )
(T
,Z
可以是任何东西)时,在定义为何体内我应该使用std::move(Z)
,因为Z
已经由右值引用传递了,何时应该我使用std::move
吗?
- When defining
foo (T && Z )
(T
,Z
can be anything), in the body of the definition Why on earth I should usestd::move(Z)
sinceZ
is already passed by an rvalue reference and when should I usestd::move
?
推荐答案
您必须了解std::move
不会移动任何内容,而是将其参数标记"为右值引用.从技术上讲,它将类型转换为右值引用.然后,右值引用将由相应的move构造函数或move赋值运算符移动.对于仅包含具有琐碎的移动ctor/赋值运算符的成员的对象,移动ctor/赋值运算符是琐碎的并且只是复制.通常,对象的移动ctor/赋值运算符会调用其所有成员的移动ctor/赋值运算符.
You have to understand that std::move
does not move anything, but "marks" its argument to be a rvalue reference. Technically, it converts the type to a rvalue reference. Then, the rvalue reference it's being moved by the corresponding move constructor or move assignment operator. For objects that contain only members with trivial move ctors/assignment operators, the move ctor/assignment operator is trivial and simply copies. In general, the move ctor/assignment operator of the object calls the move ctor/assignment operator of all its members.
所以,只要你写
int x = 10;
int y = std::move(x);
在分配y = std::move(x)
右侧的
,您有一个类型为int&&
的右值引用.但是,int
没有简单的移动ctor,并且将右值简单地复制到y
中,在x
中没有任何更改.
on the right hand side of the assignment y = std::move(x)
, you have a rvalue reference of type int&&
. However, int
does not have a non-trivial move ctor, and the rvalue is simply copied into y
, nothing is changed in 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
的move构造函数启动,并窃取"(即交换内部指针等)s
的资源,因为后者是右值引用.最后,s
将不包含任何元素.
is different. The move constructor of moved_s
kicks in, and "steals" (i.e. swaps internal pointers etc) the resource of s
, because the latter is a rvalue reference. At the end, s
will not contain any element.
这篇关于移动构造函数和std :: move混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!