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 apply std::move

    ravlue references to an element?
  • After B.key

    and B.value

    were moved, they were both canceled, but B

    as a class object A

    is no longer valid?
  • What if I have A a(A())

    , A()

    apparently, rvlaue, can I A()

    navigate to std::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?

  1. When determining foo (T && Z )

    ( T

    , z

    can be anything) in the body of the definition. Why on earth should I use std::move(Z)

    since it is z

    already passed by reference rvalue, and when do I use std::move

    ?
+3


source to share


2 answers


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 .

+8


source


  • 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.

  1. "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.

  1. For A(B())

    the compilation B

    should be a name that you have not yet defined. (Did you mean A(A())

    ? If yes, then the answer is "Yes").

  2. See 2

  3. Use std::move(Z.foo)

    whenever you want to quit Z.foo

    instead of copying from Z.foo

    .

+1


source







All Articles