The role and usage of std:move() in C++11

Official document: http://www.cplusplus.com/reference/utility/move/?kw=move

Function: Return the rvalue reference of the incoming parameter. The concept of rvalue references was only proposed in C++11. Before that there was only one kind of citation.

Pros: Calling this function does not cause any data races. (Calling this function introduces no data races.)

说明:

This is a helper function to force move semantics on values, even if they have a name: Directly using the returned value causes arg to be considered an rvalue.

Generally, rvalues are values whose address cannot be obtained by dereferencing them, either because they are literals or because they are temporary in nature (such as values returned by functions or explicit constructor calls). By passing an object to this function, an rvalue that refers to it is obtained.

Many components of the standard library implement move semantics, allowing to transfer ownership of the assets and properties of an object directly without having to copy them when the argument is an rvalue.

Although note that -in the standard library- moving implies that the moved-from object is left in a valid but unspecified state. Which means that, after such an operation, the value of the moved-from object should only be destroyed or assigned a new value; accessing it otherwise yields an unspecified value.

In general, rvalues ​​are values ​​whose address cannot be obtained by dereferencing because they are literal or temporary in nature (for example, values ​​returned by functions or explicit constructors). By passing an object to this function, an rvalue that refers to that object can be obtained.

Many components of the standard library implement move semantics, allowing ownership of an object's assets and properties to be transferred directly without copying the arguments when they are rvalues.

Be aware - in the standard library - that moving means that the object being moved from is in a valid but unspecified state. This means that after this operation, only the value moved out of the object should be destroyed or assigned a new value; otherwise accessing it yields an unspecified value.

Look at the example code:

// move example
#include <utility>      // std::move
#include <iostream>     // std::cout
#include <vector>       // std::vector
#include <string>       // std::string

int main () {
  std::string foo = "foo-string";
  std::string bar = "bar-string";
  std::vector<std::string> myvector;

  myvector.push_back (foo);                    // copies
  myvector.push_back (std::move(bar));         // moves

  std::cout << "myvector contains:";
  for (std::string& x:myvector) std::cout << ' ' << x;
  std::cout << '\n';
  
  std::cout << "foo:"<<foo<<'\n';
  std::cout << "bar:"<<bar<<std::endl;

  return 0;
}

The output is as follows:

myvector contains: foo-string bar-string
foo:foo-string
bar:

See the function of move.

See if you don't use std::move() to compare:

// move example
#include <utility>      // std::move
#include <iostream>     // std::cout
#include <vector>       // std::vector
#include <string>       // std::string

int main () {
  std::string foo = "foo-string";
  std::string bar = "bar-string";
  std::vector<std::string> myvector;

  myvector.push_back (foo);                    // copies
  myvector.push_back (bar);         // moves

  std::cout << "myvector contains:";
  for (std::string& x:myvector) std::cout << ' ' << x;
  std::cout << '\n';
  
  std::cout << "foo:"<<foo<<'\n';
  std::cout << "bar:"<<bar<<std::endl;

  return 0;
}

The output is as follows:

myvector contains: foo-string bar-string
foo:foo-string
bar:bar-string

The explanation for this example in the reference:

The first call to myvector.push_back copies the value of foo into the vector (foo keeps the value it had before the call).
The second call moves the value of bar into the vector. This transfers its content into the vector (while bar loses its value, and now is in a valid but unspecified state).

The first call to myvector.push_back will copy the value of foo into the vector (foo retains the value before the call).
The second call moves the value of bar into the vector. This transfers its contents into the vector (while bar loses its value and is now in a valid but unspecified state).

Guess you like

Origin blog.csdn.net/grf123/article/details/105379337
Recommended