1. 程式人生 > 其它 >C++的左值和右值

C++的左值和右值

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(理解成“水”),然後再讓引用繫結到該左值上(理解成在水桶上貼標籤)。

總結

本文介紹了對左值和右值的理解。如果有什麼錯誤,希望讀者可以批評指正!

參考