這個部分涉及到引用的原理性描述還是涉及到需要理解的部分的。
問題出現在當你向一個本來形參是一個引用的函數里面傳參數時,你傳的并不是一個具體的數值,而是一個表達式,這會出現一個什么樣的結果呢?C++ Primer Plus中說大部分編譯器會告訴你這是個錯誤,我驗證了一下,還真是個錯誤,如下圖所示:
那這是為啥呢?那是因為一個函數形參最終還是只會接收一個實參而不是表達式,那么這個表達式就會計算出一個中間值,然后形參中的引用就會指向這個中間值,因為中間值是臨時性的,用完了就沒了,而一個引用不能指向一個稍縱即逝的變量,所以它會報錯。
但是,如果在形參列表中加上const使之成為const引用,那就可以正常運行了,如下圖所示:
那么為什么在這種情況下就可以了呢?想知道答案必須先知道一個新詞,叫lvalue,那什么叫lvalue呢?它是一個能夠取得地址的數據對象,在C語言中通常被稱為左值,因為它們有個確切的地址。而那些文字常量和表達式則屬于非左值。而編譯器產生中間值只在下面兩個情況下。
1、實參類型就是形參類型,但是它不能作為左值,換句話說它只有一個臨時性的地址可供訪問。
2、實參類型和形參類型不匹配,但是它能夠轉換成形參類型。
一個形參是const引用只有在上面兩種情況下才會產生中間值,而這個中間值的生命期也只是函數的生存期而已。C++認為非const代表你想去改變值,const代表你想只讀值。這是合理的,因為你使用const去修飾形參很顯然就是想在函數中只讀取實參的值,只是去使用它,而不想做別的。所以在這種情況下即使產生中間值也是合法的,合理的。那么這就可以解釋為什么非const引用不能接受表達式實參了,因為生成的中間值是臨時性質的,對這個中間值進行更改必然不會影響到真正的實參,而你使用非const引用的很大目的就是去改變實參,這就不符合你的初衷了,所以在上述兩種情況下也就會報錯了。看下面的例子: