1. 什麼是rValue?lValue呢?
rValue主要是指沒有名字的變數(即臨時變數/對象);lValue主要是指有名字的變數。除了lValue都是rValue(廢話)。下面的例子可以比較直觀的協助理解:
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的文法 -- &&
3. rValue reference的意義 -- move語義。我的理解是:通過把&&聲明定義為rvalue reference,從而區分開來lvalue和rvalue,從而提供了實現move語義函數的渠道。所以,rvalue reference是實現move語義的橋樑和途徑。
4. 如何使用rValue reference來獲得move的benefit?
對於你自己實現的class,你需要實現兩個move語義的函數: move constructor和move operator=,如下:
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;}
// ...
};
然後,你有如下兩種途徑來調用到這個class move語義的實現:
1)賦值一個rvalue的clone_ptr:clone_ptr p2 = clone_ptr(new derived());
2)通過std::move來顯式的從一個lvalue擷取一個rvalue reference:
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: /EHsc
#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. 進展
VC++2010在STL的實現中已經加入了move語義,因此其中的string,vector等class都已經支援move語義了。就算你沒有顯式的調用std::move來獲利,當你構造比如臨時的string對象時(string s = string("h") + "e" + "ll" + "o";),運行時你已經享受到了move語義所帶來的效率提升。
結論就是:你的代碼中把臨時變數賦值給另一個變數的地方,運行時都已經在使用move語義了!
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: &&