C 霧中風景10 聊聊左值,純右值與將亡值

2021-09-20 07:56:35 字數 2535 閱讀 6565

1.左值與右值

左值(lvalue)和右值(rvalue)是c++型別系統之中的基礎概念,我們不需要了解這些基礎概念,同樣也能寫出**。但是如果沒有弄清左右值的概念,對於許多c++高階特性的探索會一葉障目,所以筆者嘗試總結一下自己對於左值與右值的理解。

在c++11之前的版本,基本沿用了c語言之中對於左值與右值的定義,說起來也很簡單:「在c++之中的變數只有左值與右值兩種:其中凡是可以取位址的變數就是左值,而沒有名字的臨時變數,字面量就是右值」。正是因為這兩種變數分別位於=的左右兩側,所以被命名為左值與右值。下面,舉個栗子:

int x;

int y;

x = 1;

y = 2;

x = y;

y = x;

// 以下**有誤

3 = x;

x + y = 4;

通過上述的**我們可以快速的理解,顯然x,y作為變數可以存在=的左側,而稱之為左值,而3,x + y作為字面量或中間結果,沒有辦法取得位址,則稱之為右值。這裡筆者也給乙個簡單判定的左右值的方式:

判斷能否取值的位址,能取位址的就是左值。

2.將亡值

其實上一節對於左值右值的描述,在我們編寫絕大多數**的場景下並沒有什麼影響。而在c++11擴充套件了右值的的概念,將右值分為了純右值(pure rvalue)將亡值(expiring value)。純右值的概念等同於我們之前所理解的右值,指的是臨時變數或字面量值;而將亡值是c++11新引入的概念,它依託於右值。

左值,純右值與將亡值

在c++之中,使用左值去初始化物件或為物件賦值時,會呼叫拷貝建構函式或賦值建構函式。而使用乙個右值來初始化或賦值時,會呼叫移動建構函式或移動賦值運算子來移動資源,從而避免拷貝,提高效率。而將亡值可以理解為通過移動構造其他變數記憶體空間的方式獲取到的值。在確保其他變數不再被使用、或即將被銷毀時,來延長變數值的生命期。而實際上該右值會馬上被銷毀,所以稱之為:將亡值

上述概念闡述的略微抽象,我們來看下面這段**:

這是我們簡單定義的time類,在類中我們定義了拷貝建構函式和移動建構函式:

class time 

time(const time& t)

time(time&& t) noexcept:hour(t.hour),minute(t.minute),second(t.second)

~time()

};

接下來我們執行下面的**:

int main()

執行結果:

copy

call ~time()

call ~time()

由上述**我們看到test2物件呼叫了拷貝建構函式來構造了新的物件,這個過程顯然是更占用記憶體的。而接下來,我們嘗試利用move函式將test強行轉化為將亡值,來避免記憶體重新分配的過程。但是之後我們也無法再訪問test物件的內容了,因為都在移動建構函式之中置為了空指標

int main()

執行結果:

move

call ~time()

call ~time()

通過這樣的方式來減少不必要的記憶體操作。但是之後我們也無法再訪問test物件的內容了,因為都在移動建構函式之中置為了空指標。將亡值通過移動建構函式」借屍還魂「,通過test2變數延續了自己的生命週期。

3.左值的一些"坑"

雖然筆者給出了左右值分辨的一些基本標準,但是還是有下面一些很讓人迷惑的場景:

true ? i : i;
i++ // 左值

++i // 右值

i[10]
*i
「hello world」
這是一些表示左值的特殊情況,這裡筆者也不展開一一贅述了,希望大家可以簡單的進行記憶。當然,筆者從來不去記一些太瑣碎的問題,因為太他喵難記了,所以在c++11之中,可以標準庫中新增的模板類is_lvalue_reference來判斷表示式是否為左值,is_rvalue_reference來判斷是否為右值。

cout << is_lvalue_reference::value << endl;

cout << is_rvalue_reference::value << endl;

返回1則為真,0為假。

4.小結

c 左值與右值

在學c 過程中,左值與右值的概念是一道繞不過去的坎,因此就想寫一些自己的理解。左值 lvalue 與右值 rvalue 是c 語法中的術語 terms 第一次看到這兩個詞的時候,很自然就認為在乙個表示式中,在等號左邊的就是左值,在等號右邊的就是右值。如果你們第一次看到這兩個詞也這麼認為的話,那我要恭...

C 左值與右值

左值 lvalue 和右值 rvalue 是 c c 中乙個比較晦澀基礎的概念,不少寫了很久c c 的人甚至沒有聽過這個名字,但這個概念到了 c 11 後卻變得十分重要,它們是理解 move forward 等新語義的基礎。左值與右值這兩概念是從 c 中傳承而來的,在 c 中,左值指的是既能夠出現在...

C 左值與右值

乙個很常見的誤區就是左值時等號左邊的值,右值時等號右邊的值 含義 左值是指表示式結束後依然存在的持久化物件 右值是指表示式結束時就不再存在的臨時物件 左值是儲存單元內的值,即是有實際儲存位址的 右值則不是儲存單元內的值,比如它可能是暫存器內的值也可能是立即數。下圖取自乙個知乎的回答 看幾個例子 in...