In the previous section we proposed an rvalue reference that could be used to differentiate the right value, so what's the use?
Source of the problem
Let's look at a question that has been criticized in C + + for a long time:
I read the contents of a file into a vector, how do I encapsulate it with a function?
The way most people do this is:
void readFile (conststring &filename, vector<string> &words) { words.clear (); // Read XXXXX}
This is completely doable, but the code style is far from beautiful, and we're trying to write:
vector<string> ReadFile (conststring &filename) { vector< String> ret; Ret.push ("CESFWFGW"); // .... // return ret;}
So we can call this in main:
vector<string> coll = readFile ("fef.text");
However, a little familiarity with C + + knows that this can cause a lot of overhead in syntax:
RET is copied to the TEMP variable, and the temporary variable is opened on the heap
Temporary variable copied to Coll
This results in two copies and destruction overhead.
If this is the case, you can use the code at the beginning to solve the overhead, so if it is a function that the query returns the result, then we have to write this:
vector<string> Queryword (conststring &word) { vector< String> result; // XXXXX return result;}
There is no way to avoid the overhead.
Introduction of moving semantics
Let's consider a common problem in life (here's how to evaluate C++11 's rvalue reference (Rvalue reference) feature? ), if you move a heavy cargo from box A to box B, then
The normal practice is to open box A, move the item out, move to B, and then close a.
Another wonderful thing to do is to copy an item A in B and destroy it in a.
The more exotic way is: because of the limitations of the replication tool, we can not directly copy in B, so we have to copy an item on the ground temp, destroy the item in a, and then according to temp in B copy another, and then destroy the ground temp.
In fact, c++98 is using the last very inefficient approach, and the key here is that c++98 does not differentiate between "copy" and "Move" semantics very well .
In the above problem, we explicitly proposed moving a to B, but c++98 due to the lack of moving semantics, had to use copy to complete the way.
Let's go back to the beginning of the question:
vector<string> ReadFile (conststring &filename) { vector< String> ret; Ret.push ("CESFWFGW"); // .... // return ret;}
Here we must see a point, after the completion of the function call, RET will be destroyed, so we think of an idea, not to copy the contents of RET to main Coll, but the ret in the content of stealing into the Coll , and then the RET quietly destroyed.
This is possible because the life cycle of RET is very short.
What can be stolen?
Now the question is, which of C + + can be stolen and which cannot?
We look back at the four expressions mentioned in the previous section:
string One ( " one " const string ( " two " string three () {return " three " ; const string Four () {return " four "; }
Obviously, one and both life cycles are longer and cannot be stolen. Four has a const attribute and refuses to be stolen.
Then three can be stolen, because it is a temporary variable, and there is no const attribute.
Therefore, thenon-const rvalue in C + + is exactly the same as the move semantics .
In the previous section we proposed to use rvalue reference to distinguish right value, is to solve what can steal the problem!
OK, we have a very clear idea:
1. In order to solve the return object cost problem, we propose "steal" instead of copying the object
2. We face the problem of what we can steal and what we cannot steal.
3. The right value can be stolen, so how do we differentiate the right value?
4. We introduce the Rvalue reference x && to differentiate the right value.
This is the source of the rvalue reference.
If a variable is not an rvalue, but we need to steal it, then we can use the Std::move function to force it into an rvalue reference .
For example:
void Test (string name) { string temp (std::move (name)); // XXXXXX}
Note that the name after being stolen cannot continue to be used, so the move function is not free to use.
The impact
So what does an rvalue reference bring to the change?
The first is to assign a value to the member function of the class, see the following code:
classpeople{ Public: People () {cout<<"people ()"<<Endl; } people (Const string&name): name_ (name) {cout<<"people (const string &name)"<<Endl; } people (string&&name): name_ (name) {cout<<"people (string &&name)"<<Endl; }Private: stringname_;};
Here name assignment, we provide an rvalue function relative to c++98, and move the value of name to Name_.
In fact, the above two functions can synthesize one:
class people{public: people () { "people ()" << Endl; } People (string name) : Name_ (std::move (name)) { " People (string name)" << Endl; } Private : string name_;};
Note here that the above name takes a value, and it does not bring overhead because:
If name is passed to an rvalue, then name itself is a mobile construct, with a much smaller cost than replication, equivalent to people (string &&name)
If name is passed in to another value, then name is a copy construct and then moved to name_, without adding additional overhead.
For constructors, you need to move the constructor , in addition to providing a copy constructor. As follows:
classpeople{ Public: People () {cout<<"people ()"<<Endl; } people (stringname): Name_ (Std::move (name)) {cout<<"people (string name)"<<Endl; } people (ConstPeople &p): Name_ (p.name_) {cout<<"people (const people &p)"<<Endl; } people (People&&p): Name_ (Std::move (p.name_)) {cout<<"people (People &&p)"<<Endl; }Private: stringname_;};
Note In the last people (People &&p), when you move the name in P, you must explicitly use Moveto force the name member to be moved.
Similarly, there are move assignment operators .
In addition, in the c++98, the element inside the container must have value semantics, now is different, the element has the ability to move, later we will refer to the unique_ptr in the Smart pointer series, it can be placed in the vector, but does not have the ability to copy and assign value.
Other effects please refer to: How to evaluate the Rvalue reference (Rvalue Reference) feature of c++11?
The following is a simulation implementation of a string that demonstrates the use of an rvalue reference.
C++11 rvalue Reference (ii): rvalue Reference and move semantics