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

總結

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

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM