2014-10-19 57 views
0

有很多關於右值(引用)的線程。C++中的Rvalue(引用)11

但我還沒有找到了答案,我的以下問題:

http://en.cppreference.com/w/cpp/utility/move,性病::移動()需要一個右值引用作爲參數。

根據C++ 11標準http://i.stack.imgur.com/YKlod.png中的圖表,左值不會是右值。

的標準::移動()常見的用法:

Foo f; 
std::deque<Foo> fq; 
fq.push_back(std::move(f)); 

f是一個左值,因爲它是根據C++ 11標準的對象:

左值(所謂的,在歷史上,因爲左值可能出現在賦值表達式的左側)指定一個函數或一個對象。 [例如:如果E是指針類型的表達式,則* E是指向E指向的對象或函數的左值表達式。再舉一個例子,在調用它的返回類型的函數的結果是左值引用是左值。]

然後,從理論上講,性病::移動(F)應該給我一個編譯錯誤,但它不「T。我相信我錯過了一些...

歡迎任何輸入。

+2

其實,std :: move的大驚小怪。 std :: vector爲此目的具有emplace_back – 2014-10-19 00:22:35

+0

實際上,'std :: move'不是一個右值引用,而是一個轉發引用(又名通用引用),這意味着它可以是左值和右值引用。 – Deduplicator 2014-10-19 00:24:26

+0

@remyabel什麼是「崩潰規則」? – Hei 2014-10-19 00:25:13

回答

2

正如@Deduplicator所述,&&僅表示T是推導類型的情況下的通用參考。斯科特·邁耶的comprehensive blog post on Universal References提供了一個容易記住的名言:

如果一個變量或參數被聲明爲具有類型T & &一些 推導型T,該變量或參數是一個普遍的參考。

除了作爲一個代碼示例:

Widget&& var1 = someWidget; // here, 「&&」 means rvalue reference 

auto&& var2 = var1; // here, 「&&」 does not mean rvalue reference 

template<typename T> 
void f(std::vector<T>&& param); // here, 「&&」 means rvalue reference 

template<typename T> 
void f(T&& param);    // here, 「&&」does not mean rvalue reference 

作爲覆蓋Thomas Beckerstd::move接受通用參考採取完善轉發優勢。

儘管push_back採用T&&,但這不是一個通用參考,正如Scott Meyers所解釋的。 T已經推導出在這種情況下:

template <class T> 
void vector<T>::push_back(T&& x); 

因此參數實際上變成一個右值引用。舉一個實際的例子,認爲不具有重載需要一個左值參考模板類:

template <typename T> 
struct Test 
{ 
    void push_back(T&& t); 
}; 

template <typename T> 
void Test<T>::push_back(T&& t) { std::cout << "rvalue overload.\n"; } 

int main() 
{ 
    Test<int> t; 
    t.push_back(42); 
    int i = 50; 
    t.push_back(i); 
    return 0; 
} 

t.push_back(i)會給出一個錯誤。

0

「右值引用」並不意味着是右值的引用。這只是對類型的描述(T&&而不是T&)。在這方面這是令人困惑的命名。價值類別f確實是左值這很好。

3

std::move的參數是T &&類型,其中推導出T。這就是所謂的轉發參考。*

的訣竅是由模板生成的聲明T & &&相當於T &。當您通過左值intmove時,則的T &&的推導結果爲T = int &,整個參數爲int & && = int &。這被稱爲參考摺疊

正如您所看到的,將左值傳遞給右值參數是非法的,但參考摺疊可以防止發生這種情況。

通過聲明這樣一個引用來定義一個與左值或右值引用一起工作的函數的做法被稱爲完美轉發,因此該引用是一個forwading引用。參數是「轉發的」,因爲它在函數內的行爲與函數調用中的行爲相同,前提是std::forward用於恢復右值。

*術語通用編號正在編號deprecated