Move constructor and std :: move confusion
I read about std::move
, move constructor and move assignment operator. To be honest, all I have 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);}
};
- I thought this
B
is an rvalue reference, why can you applystd::move
ravlue references to an element? - After
B.key
andB.value
were moved, they were both canceled, butB
as a class objectA
is no longer valid? - What if I have
A a(A())
,A()
apparently, rvlaue, can IA()
navigate tostd::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; }
What if I call add(5)
, how 5
can I move and why? And notice that it z
was moved twice, after it z
was moved the first time, it was not valid, how can you move it again?
- When determining
foo (T && Z )
(T
,z
can be anything) in the body of the definition. Why on earth should I usestd::move(Z)
since it isz
already passed by reference rvalue, and when do I usestd::move
?
source to share
You should understand that std::move
nothing moves, but "marks" its argument as an rvalue reference. Technically, it converts the type to an rvalue reference. Then, the rvalue refers to its move with the appropriate move constructor or move assignment operator. For objects that only contain elements with trivial move / assignment operators, the ctor move / assignment operator is trivial and just copies. In general, the ctor / assignment operator of an object calls the ctor / assign operator of all its members.
So, whenever you write
int x = 10; int y = std :: move (x);
on the right side of the assignment y = std::move(x)
, you have an rvalue reference of type int&&
. However, int
there is no non-trivial move of the ctor and the rvalue is just copied to y
, nothing changes to x
.
On the other hand,
string s = "some string"; string moved_s = std :: move (s); // here we tell the compiler that we can "steal" the resource of s
is different. The move constructor moved_s
runs and "steals" (ie, swaps internal pointers, etc.) the resource s
because the latter is an rvalue reference. s
Will not contain any element at the end .
source to share
-
B
is the name of the object. Once the link has been attached, it names the object. The distinction between "rvalue reference", "lvalue reference" and "named object" only applies to how the name can be linked before you get there.
B.key
is the name of the variable in the object that was supplied as an argument to this function call.
- "invalidated" is not standard move terminology. Standard library objects remain in an unspecified state after being moved from; but that's not what's going on here.
The line A.key = std::move(B.key)
calls the inline assignment definition for int
(this is a simple assignment, not a function call), which is just a copy. Thus, it B.key
retains its value.
-
For
A(B())
the compilationB
should be a name that you have not yet defined. (Did you meanA(A())
? If yes, then the answer is "Yes"). -
See 2
-
Use
std::move(Z.foo)
whenever you want to quitZ.foo
instead of copying fromZ.foo
.
source to share