move constructor and std::move confusion

别说谁变了你拦得住时间么 提交于 2019-12-22 04:13:19

问题


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);}
};
  1. I thought B is an rvalue reference, why you can apply std::move to an ravlue reference's member?
  2. After B.key and B.value have been moved, both have been invalidated, but how B as an object of class A gets invalidated?
  3. What if I have A a(A()), A() is apparently an rvlaue, can A() be moved by std::move and why?
  4. 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 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?

  1. When defining foo (T && Z )(T, Z can be anything), in the body of the definition Why on earth I should use std::move(Z) since Z is already passed by an rvalue reference and when should I use std::move?

回答1:


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.

So, whenever you write

int x = 10;
int y = std::move(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.

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




回答2:


  1. B is the name of an object. Once a reference has been bound, it names an object. The distinction "rvalue reference", "lvalue reference" and "named object" only applies to how the name can be bound before you got this far.

B.key is the name of a variable in the object which was supplied as argument to this function call.

  1. "invalidated" is not part of the standard terminology for moving. Standard library objects are left in an unspecified state after being moved out of; but that's not what's going on here.

The line A.key = std::move(B.key) invokes the built-in definition of assignment for an int (this is a simple assignment, not a function call), which is just a copy. So B.key retains its value.

  1. For A(B()) to compile, B must be a typename which you haven't defined yet. (Did you mean A(A()) ? If so, then the answer is "Yes").

  2. See 2

  3. Use std::move(Z.foo) whenever you want to move out of Z.foo instead of copying from Z.foo.



来源:https://stackoverflow.com/questions/27497830/move-constructor-and-stdmove-confusion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!