右值並不能取到地址,所以左值引用不能綁定到右值,但是常量左值引用為什麼就可以呢?其中的數據在內存中的存儲狀況是怎麼樣的一個情況?


C++ 2.0 前,引用沒有左右值的限制。

The reason to allow references to be initialized by non-lvalues was to allow the distinction between call-by-value and call-by-reference to be a detail specified by the called function and of no interest to the caller. For const references, this is possible; for non-const references it is not. For Release 2.0 the definition of C++ was changed to reflect this.

允許引用綁定非左值的初衷在於「讓傳值還是傳引用成為函數本身的細節,調用者不用去關心」,這一點,在 const 引用上可以達到,而非 const 引用調用者沒法不關心傳值還是傳引用,所以乾脆禁止掉了。C++ 2.0 特意為此在語言方面作出了調整。

其實不僅是無法實現初衷,非 const 引用綁定非左值還會讓 C++ 變「坑」,Bjarne 意識到了這樣做的問題:

I made one serious mistake, though, by allowing a non-const reference to be initialized by a non-lvalue. For example:

void incr(int rr) { rr++; }

void g()
{
double ss = 1;
incr(ss); // note: double passed, int expected
// (fixed: error in Release 2.0)
}

Because of the difference in type the int cannot refer to the double passed so a temporary was generated to hold an int initialized by sss value. Thus, incr() modified the temporary, and the result wasnt reflected back to the calling function.

如果允許任何引用綁定非左值,會帶來代碼合法,但是邏輯錯誤的很難察覺的「坑」。

除了上述「初衷」外,支持綁定非左值還有一個硬性需求:

It is important that const references can be initialized by non-lvalues and lvalues of type that require conversion. In particular, this is what allows a Fortran function to be called with a constant:

extern "Fortran" float sqrt(const float);

void f()
{
sqrt(2); // call by reference
}

為了支持 Fortran 足夠服人了吧?

以上引用出自《C++ 設計與演化》。
因為以前根本就沒有左值引用的說法。所有的blah都叫引用,命名上根本不關心綁的是左值還是右值。所以這個規則應該叫「常引用可以綁定到右值」,這樣聽起來就沒啥問題了。


常量左值引用 在c98中被稱為"萬能「引用類型

他可以接受:非常量左值,常量左值,右值對其初始化例如:

int d = 100;

const int e = 100;

const int c = d;//接受一個非常量左值

const int v = e;//接受一個常量左值

const int z = 3 + 4;//接受一個右值

關於右值引用的說明可參考:c++ 11 移動語義、std::move 左值、右值、將亡值、純右值、右值引用


看來題主還是懶得看我答案啊,真的挺無奈的。我挺不喜歡幫人研究,不過答了就要敬業:

例子1

int main()
{
const int a = 53;

const int a = 53;

009A1808 mov dword ptr [ebp-18h],35h // 53 被放到了棧里 009A180F lea eax,[ebp-18h] 009A1812 mov dword ptr [a],eax

例子2

const int a = 53;

int main()
{
std::cout &

std::cout &010625BE mov esi,esp 010625C0 push offset std::endl& &> (01061064h) 010625C5 mov edi,esp 010625C7 mov eax,dword ptr [a (0106A138h)] // 53 被放在了堆上010625CC mov ecx,dword ptr [eax] ------------------------------------------------自己寫一句然後看看反彙編代碼。

不想寫的。但是看了很多類似的問題。別的答案 一些垃圾半吊子 扯了半天 什麼 const 引用安全,, 真是吐了, 人要有自己思想啊。 還是本答案靠譜回答多


詳見《C++ Primer Plus》(第六版) 262頁


推薦閱讀:
相关文章