C++的左值和右值
阿新 • • 發佈:2022-03-20
C++的左值和右值
摘要
C++語言中的左值和右值是困擾我的知識點,今天將學習到的知識點整理一下,以理清概念。本文首先介紹了左值、右值的一般分類和概念,包括廣義左值,將亡值和純右值,然後介紹了我對左值和右值的理解:將左值理解成水桶,將右值理解成水,最後介紹了左值引用和對常量的左值引用。
表示式值的分類
本文說的左值(lvalue)和右值(rvalue),其中的“值”就是表示式(expression)的值。C++17標準定義了表示式值的分類,其主要分為3類:
- 廣義左值(glvalue):在程式設計師程式設計時,程式設計師可以取地址的東西(物件、函式)。舉例:變數、函式等。
- 純右值(prvalue):在程式設計師程式設計時,程式設計師不可以取地址的東西。舉例:字面值常量。
- 將亡值(xvalue):本身可以被程式設計師取地址,但是馬上就不能被取地址了的東西。
這三種類別和左右值的關係圖:
三種類別和左右值的關係圖
左右值的理解
我把左值理解成水桶,右值理解成水。這樣我感覺比較好記憶和理解。比如:
int x; //x左值,理解成一個水桶
x = 10; // 10是右值,理解成水
int *p = &x; // 可以對水桶取地址,找到放水桶的地址
&10; // 編譯錯誤,水沒有位置,不能取地址
int y = x; // 把x水桶裡的水複製一份到y水桶。
又如:
int f() { int x = 10; // x是一個水桶 return x; //但是要被返回了,也就是這個水桶要被“銷燬”。 } int main() { f() = 10; //編譯錯誤,水桶已被銷燬,不能盛水了 return 0; }
左值引用
左值引用,就是在水桶上貼上了一個標籤,這個標籤代表了水桶(其實變數名字也可以理解成水桶上的標籤)。
比如:
int a = 10;
int &b = a; //貼上標籤
注意到常量的左值引用可以繫結到字面值常量上,也就是說以下程式碼是正確的:
const int & c = 10; //編譯正確,但是“10”是右值,理解成水,c是左值引用,理解成標籤。
但是如果把左值引用理解成在水桶上貼標籤的話,以上程式碼就與這個理解產生衝突了。畢竟“標籤”不能貼到“水”上。
其實,編譯器會建立一個隱藏的變數來讓引用c
繫結到10
上。比如:
const int & c = 10; //會被翻譯成這樣: int __internal_unique_name = 10; const int& c = __internal_unique_name;
也就是說,編譯器會建立一個左值(理解成“水桶”)來儲存10(理解成“水”),然後再讓引用繫結到該左值上(理解成在水桶上貼標籤)。
總結
本文介紹了對左值和右值的理解。如果有什麼錯誤,希望讀者可以批評指正!
參考
- [1]微軟C++文件
- [2]Internal Pointers的部落格