1. Introduction
When learning to use move, we should first distinguish the left value and right value in C + +.
Because the distinction between left value and right value is complex, we can adopt a simplified view, which will meet our purpose to a great extent.
Lvalue
The simplest approach is to treat lvalues (also known as locator values) as functions or objects (or expressions that evaluate to functions or objects). All lvalues are allocated memory addresses. When lvalues are initially defined, they are defined as "values suitable for the left side of the assignment expression". However, the const keyword was later added to the language, and the lvalue is divided into two subcategories: modifiable lvalue (which can be changed) and immutable lvalue (const).
Right value
The simplest way is to think of the right value as "everything that is not a left value". This includes literal quantities (e.g., 5), temporary values (e.g., x+1), and anonymous objects (e.g., scores (5,2)). Right values are usually calculated based on their values, have an expression range (they terminate at the end of the expression in which they are located), and cannot be assigned.
2. Use of STD:: move
Let's take a look at the use of string exchange through an example.
#include <iostream> #include <string> template<class T> void myswap(T& a, T& b) { T tmp{ a }; // Reference copy construction a = b; // Assignment using copy b = tmp; // Assignment using copy } int main() { std::string x{ "abc" }; std::string y{ "de" }; std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; myswap(x, y); std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; return 0; }
The above example is to exchange two strings, but it will be copied three times during the exchange, resulting in the creation and destruction of too many strings and reducing the efficiency of the program. What method can be used to solve this problem?
This is mainly because a and b are lvalues. In c++ 11, std::move is a standard library function, which (using static_cast) converts its parameters into an rvalue reference, so that the move semantics can be called. Therefore, we can use std::move to convert the lvalue to a type that prefers moving rather than copying. Move is defined in the program header file.
The following is the same program as above, but uses a myswap() function, which uses std::move to convert the l value to the r value, so that we can call the move semantics:
#include <iostream> #include <string> #Include < utility > / / use std::move template<class T> void myswap(T& a, T& b) { T tmp{ std::move(a) }; // Using the move construct a = std::move(b); // Assignment using move b = std::move(tmp); // Assignment using move } int main() { std::string x{ "abc" }; std::string y{ "de" }; std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; myswap(x, y); std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; return 0; }
3 Comparison
The above two examples do not show the use of move, so use the next example to show the difference between move and copy
#include <iostream> #include <string> #include <utility> #include <vector> int main() { std::vector<std::string> v; std::string str = "Knock"; std::cout << "Copying str\n"; v.push_back(str); // Using the lvalue reference version, copy str to the array array std::cout << "str: " << str << '\n'; std::cout << "vector: " << v[0] << '\n'; std::cout << "\nMoving str\n"; v.push_back(std::move(str)); // Using the right value reference version, move str into the array array std::cout << "str: " << str << '\n'; std::cout << "vector:" << v[0] << ' ' << v[1] << '\n'; return 0; }
It can be clearly seen from the above example that the value in str does not change during copying, but in the moving example, the value in str has disappeared, that is, the value is really moved out.
Article through website https://www.learncpp.com/cpp-tutorial/rvalue-references/ study