C C 左值 右值及引用

2022-08-17 20:36:12 字數 3552 閱讀 6883

目錄

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 語法做的優化,引用的本質還是靠指標...