目錄
c和c++中定義了引用型別(reference type),存在左值引用(lvalue reference)。而在c++11中,新增了右值引用(rvalue reference)這一概念, 雖然個人感覺右值引用用處不大,但在此一併討論。首先,我們討論左值和右值兩個概念。
左值(lvalue):乙個標識非臨時性物件的表示式。通常來說,可以將程式中所有帶名字的變數看做左值。
右值(rvalue):相對的,右值標識是臨時性物件的表示式,這類物件沒有指定的變數名,都是臨時計算生成的。
考慮以下**:
vectorarr(3);
const int x = 2;
int y;
int z = x + y;
string str = "foo";
vector*ptr = &arr;
在上述**中,arr, str, y, z等都是左值,x也是乙個左值,且他不是乙個可修改的左值;而類似於2, x+y這類臨時(沒有專屬變數名)的值則是右值。
我們可以這樣理解引用:乙個引用是它所引用物件的同義詞,是其另乙個變數名。
看這樣一段**:
#inclulde int main()
執行結果如下:
(1)左值引用
左值引用的宣告是通過在某個型別後放置乙個符號&來進行的。前文**中的int & y = x;
便是乙個左值引用。
需要注意的是,在定義左值引用時,=右邊的要求是乙個可修改的左值。因此下面幾種左值引用都是錯誤的:
#include int main()
編譯執行,報錯如下:
(2)右值引用
類似於左值引用,右值引用便是對右值的引用,它是通過兩個&&來宣告的。
#include int main()
執行結果如下:
引用和指標的區別我們知道,指標是在記憶體中存放位址的一種變數,cpu能夠直接通過而變數名訪問唯一對應的記憶體單元,且每個記憶體單元的位址都是唯一的。因為目前右值引用用途不大,故此處僅列舉較為常見的左值引用用途而變數名和引用,都可以看做記憶體的乙個標籤或是識別符號,計算機通過是否符合識別符號判斷是否為目標記憶體,而乙個記憶體可以有多個識別符號
(1)作為複雜名稱變數的別名
我們可以寫出類似如下的語句:
auto & whichlist = thelist[myhash(x, thelist.size())];
可以看到,我們用簡短的whichlist
代替了其原本複雜的名稱,這能夠簡化我們的**書寫。
(2)用於rangefor迴圈
設想我們希望通過rangefor迴圈使乙個vector物件所有值都增加1,下面的rangefor迴圈是做不到的、
for (auto x : arr) // x僅相當於每個元素的拷貝
++x;
但我們可以通過使用引用達到這一目的
for (auto & x : arr)
++x;
(3)避免複製大的物件假定有乙個findmax函式,它返回乙個vector中最大的元素。若給定vector儲存的是某些大的物件時,下述**中的x拷貝返回的最大值到x的記憶體中:
auto x = finamax(vector);
在大型的專案中這顯然會增大程式的開銷,這時我們可以通過引用來減小這類開銷
auto & x = findmax(vector);
類似的,我們在處理函式返回值的時候也可以使用傳引用返回。但是要注意,當返回的是類中私有屬性時,傳回的引用會導致外界能夠對其修改。
(4)參與函式中的引數傳遞
在c和c++的函式中,addself(int x)
這類函式對直接傳入的引數進行修改並不會改變原有引數的值。而有時我們希望能夠實現類似swap(int a, int b)
這類能夠修改原引數的函式時,我們可以通過1.傳入指標和2.傳入引用實現。
swap函式的實現是乙個很好的例子
#include void swap_non(int, int); // 直接傳入引數
void swap_p(int *, int *); // 傳入指標
void swap_r(int &, int &); // 傳入引用
int main()
void swap_non(int a, int b)
void swap_p(int * a, int * b)
void swap_r(int & a, int & b)
執行結果如下:
可以看到,只有在傳入指標和傳入引用時變數才真正交換。
對直接傳入引數和傳入指標仍不理解的可以看這篇部落格,在此不再描述。前面我們討論3.(3)時,談到可以使用引用來減少複製產生的記憶體開銷。
考慮這樣一種情況,在進行元素交換時,我們通常使用乙個快取變數temp
來臨時儲存資料;而對temp
直接進行=的賦值操作時,實際上temp複製了一次原有物件的記憶體,但我們需要只是物件之間的移動而不是複製,而c++stl中的std::move函式便可以達成這一操作。
這可能有些抽象,讓我們通過例子來看看:
void swap(vector& x, vector& y)
上述例子是c++stl中std::swap的原始碼之一,相信它很好的示範了std::move是如何使用的,而在原始碼中使用,也足以說明它的高效。 左值 右值 左值引用 右值引用
2015 06 01 15 07 404人閱讀收藏 舉報 c 11 5 一 c 中的左值和右值 誤區 左值位於等號左邊,右值位於等號右邊。c 11中的定義 左值表示式表示的是乙個物件的身份 在記憶體中的位置 而右值表示式表示的是物件的值 內容 左值和右值都是針對表示式而言的,左值是持久的,右值是短暫...
左值 左值引用 右值 右值引用
1 左值和右值的概念 左值是可以放在賦值號左邊可以被賦值的值 左值必須要在記憶體中有實體 右值當在賦值號右邊取出值賦給其他變數的值 右值可以在記憶體也可以在cpu暫存器。乙個物件被用作右值時,使用的是它的內容 值 被當作左值時,使用的是它的位址。2 引用 引用是c 語法做的優化,引用的本質還是靠指標...
左值 左值引用 右值 右值引用
1 左值和右值的概念 左值是可以放在賦值號左邊可以被賦值的值 左值必須要在記憶體中有實體 右值當在賦值號右邊取出值賦給其他變數的值 右值可以在記憶體也可以在cpu暫存器。乙個物件被用作右值時,使用的是它的內容 值 被當作左值時,使用的是它的位址。2 引用 引用是c 語法做的優化,引用的本質還是靠指標...