值类别

所有的表达式属于两大类:泛左值 和 右值
- 泛左值包括:左值、将亡值
- 右值包括:纯右值、将亡值
泛左值
泛左值(glvalue,generalized lvalue),广义上的左值,是左值 和 将亡值 的集合。
特点:有身份
左值
左值(lvalue,left value):一个指向特定内存位置,有名称的表达式,可以获取其地址。
通俗理解:持久存储的对象,通常有变量名。
cpp
int a{10}; // a 是 左值
const double b {3.14}; // b 是 左值
int *ptr {&a}; // a 是 左值,可以获取地址 &a
std::string s {"hello"}; // s 是 左值
std::string& get_string() { return s; } // 函数返回左值引用,调用也是左值特点:
- 有身份:在程序中有自己的名字或可以获取其地址。
- 不可被移动:传统左值不能被掠夺其资源。
将亡值
将亡值(xvalue,expired value):即将消亡的值,是连接 左值 和 右值 的桥梁。
它本身有身份(曾经是左值),但被显式标记为 "它的资源可以被安全地移动走"。
通俗理解:一个生命周期即将结束的对象,通常是使用了 std::move() 或 static_cast<T&&> 转换的结果,或者是返回右值引用的函数调用。
cpp
int a {10};
std::move(a); // 将亡值
std::string str {"world"};
std::string &&rval_ref {std::move(str)}; // rval_ref 将亡值
struct MyClass {
int *data;
};
MyClass get_xvalue(); // 函数返回右值引用,调用该函数得到将亡值std::move()本质是static_cast<int&&>(a),将 左值a转换为将亡值
特点:
- 有身份:它通常对应一个明确的对象。
- 可被移动:编译器允许将它的资源转移走。
右值
右值(rvalue):一个临时的、匿名的、即将被销毁的对象,无法获取它的地址。
通俗理解:临时对象、字面量(字符串字面量除外),或者被标记为 "可被夺取资源" 的对象。

右值在 C++11 后细分为两类:纯右值、将亡值
纯右值
纯右值 (prvalue,Pure Rvalue):纯粹的右值,是右值中最经典的形式。
它通常是字面量、临时对象、返回非引用类型的函数调用。
cpp
43 // 整型字面量,纯右值
true // 布尔字面量,纯右值
3.14 // 浮点字面量,纯右值
std::string("hello") // 临时对象,纯右值
a + b // 算术运算的结果是临时值,纯右值
int foo() { return 100; }
foo() // 函数返回非引用类型,纯右值特点:
- 没有身份:无法获取其地址
- 可被移动:它的资源可以被移动到另一个对象,从而避免赋值。