1. What is rvalue? What about lvalue?
Rvalue mainly refers to variables without names (I .e. temporary variables/objects); lvalue mainly refers to variables with names. Except lvalue, It is rvalue (nonsense ). The following example can help you understand the problem intuitively:
Int & n = 42; // OK; 42 is an rvalue; n is rvalue reference.
Int K = N; // OK; n is rvalue reference and is lvalue.
Int & J = K; // error; k is an lvalue
Int & M = k + 1; // OK, k + 1 is an rvalue
A & a_ref3 = a (); // error! Note: A is a class.
A & a_ref4 = a (); // OK
Note: A rvalue Reference refers to a rvalue and is a lvalue; A lvalue Reference refers to a lvalue and is a lvalue.
2. rvalue reference Syntax --&&
3. Meaning of rvalue reference-move semantics.My understanding is: by defining & declaration as rvalue reference, we can distinguish between lvalue and rvalue, thus providing a channel to implement the move semantic function. Therefore, Rvalue reference is a bridge and path to implement the move semantics.
4. How to Use rvalue reference to obtain the benefit of move?
For your own class, you need to implement two moving Semantic Functions: Move constructor and move operator =, as shown below:
Template <class T>
Class clone_ptr
{
PRIVATE:
T * PTR;
Public:
// Construction
Explicit clone_ptr (T * p = 0): PTR (p ){}
// Destruction
~ Clone_ptr () {Delete PTR ;}
// Copy Semantics
Clone_ptr (const clone_ptr & P)
: PTR (P. PTR? P. PTR-> clone (): 0 ){}
Clone_ptr & operator = (const clone_ptr & P)
{
If (this! = & P)
{
Delete PTR;
PTR = P. PTR? P. PTR-> clone (): 0;
}
Return * this;
}
// ************ Move semantics *********************
Clone_ptr (clone_ptr & P)
: PTR (P. PTR) {P. PTR = 0 ;}
Clone_ptr & operator = (clone_ptr & P)
{
STD: swap (PTR, P. PTR );
Return * this;
}
// Other operations
T & operator * () const {return * PTR ;}
//...
};
Then, you have two ways to call the implementation of the class move semantics:
1) assign a rvalue to clone_ptr: clone_ptr P2 = clone_ptr (New derived ());
2) use STD: Move to explicitly obtain an rvalue reference from an lvalue:
Clone_ptr p1 (New derived );
//...
Clone_ptr P2 = STD: Move (P1); // P2 now owns the pointer instead of P1
5. You can cast an lvalue to an rvalue reference.
The stl std: Move function enables you to convert an object to an rvalue reference to that object. alternatively, you can use the static_cast keyword to cast an lvalue to an rvalue reference, as shown in the following example:
// Cast-reference.cpp
// Compile with:/ESCs
# Include <iostream>
Using namespace STD;
// A class that contains a memory resource.
Class memoryblock
{
// Todo: Add resources for the class here.
};
Void g (const memoryblock &)
{
Cout <"in G (const memoryblock &)." <Endl;
}
Void g (memoryblock &&)
{
Cout <"in G (memoryblock &)." <Endl;
}
Int main ()
{
Memoryblock block;
G (Block );
G (static_cast <memoryblock &> (Block ));
}
This example produces the following output:
In G (const memoryblock &).
In G (memoryblock &&).
6. Progress
VC ++ 2010 has added the move semantics to STL implementation. Therefore, all the classes such as string and vector support the move semantics. Even if you do not explicitly call STD: move to make a profit, When you construct a temporary String object such as (string S = string ("H ") + "E" + "ll" + "O";), you have enjoyed the efficiency improvement brought about by moving semantics during running.
The conclusion is: In your code, you assign a temporary variable to another variable, and you are already using the move syntax at runtime!
7. Summary:Rvalue references distinguish lvalues from rvalues. they can help you improve the performance of your applications by eliminating the need for unnecessary memory allocations and copy operations. they also enable you to write one version of a function that accepts arbitrary arguments and forwards them to another function as if the other function had been called directly.
Msdn always writes good article: rvalue reference declarator :&&