如何理解c++中的引用摺疊?


== ==


樓上幾位把結果都說得很清楚了,根本原因是因為C++中禁止reference to reference,所以編譯器需要對四種情況(也就是L2L,L2R,R2L,R2R)進行處理,將他們「摺疊」(也可說是「坍縮」)成一種單一的reference。


是零元


引用摺疊的規則上面的各位已經說得很清楚了,我在這裡補充下引用摺疊是為什麼出現的吧。

要說引用摺疊,首先得說右值引用(在看這個之前需要了解C++11中左值,右值的概念)。它是C++11出現的新概念,聲明類型的方法是:T,具體信息可以看下面的代碼:

Class A
{
A()
{// do something}
};

A GetA()
{
return A();
}

int main()
{
A a1 = GetA(); // a1是左值
A a2 = GetA(); // a2是右值引用
return 0;
}

a1是左值,在構造時使用了GetA() 產生的臨時對象,之後GetA()產生的臨時對象會銷毀。

a2是右值引用,其指向的就是GetA()所產生的對象,這個對象的聲明周期是和a2的聲明周期是一致的。即少了臨時對象,從而省去了臨時對象的構造和析構。

由此可見右值引用的好處,在新代碼中,右值引用是值得大力使用的。但是,在使用的時候,有例外情況了:T並不是一定表示右值,比如,如果它綁定的類型是未知的話,既可能是左值,又可能是右值。比如:

template&
void f(T param);

f(10); // 10是右值
int x = 10;
f(x); // x是左值

以上這種未定的引用類型(param的類型)稱為 universal references,這種類型必須被初始化,而它是左值還是右值則取決於它的初始化,如果被左值初始化,那麼它就是左值,反之亦然。那麼什麼時候是左值,什麼時候是右值,就需要進行類型推導才知道。

由於存在T這種未定的引用類型,當它作為參數時,有可能被一個左值引用或右值引用的參數初始化,這是經過類型推導的T類型,相比右值引用()會發生類型的變化,這種變化就稱為引用摺疊。(《深入應用C++11-代碼優化與工程級應用》 --- 祁宇 P68 )

引用摺疊的規則如下(配合@jun-jun的答案)[和上一段的出處一樣]:

1.所有右值引用摺疊到右值引用上仍然是一個右值引用。(A 變成 A)

2.所有的其他引用類型之間的摺疊都將變成左值引用。 (A 變成 A; A 變成 A; A 變成 A)

以上,才疏學淺,有不明確或不正確的地方,請指正。


感覺上叫引用坍塌好理解點(reference-collapsing rules)

就這樣

A 變成 A

A 變成 A

A 變成 A

A 變成 A


就是左值引用會傳染,只有純右值 = ,沾上一個左值引用就變左值引用了


推薦閱讀:

extern C裡面能有C++代碼嗎?
該如何設計實現一個telnet bbs?
C++ 中對 main 函數的地址賦值會怎樣?
關於2048局面的價值判斷及ai思路?
為什麼5%的CPU佔用會造成這麼大的性能損失?

TAG:編程語言 | 計算機 | CC | 編程語言理論 |