C++中Lvalue(左值)的定义、识别及相关问题咨询
C++左值常见问题解答
一、如何识别C++中的对象是否拥有地址
直接通过语法层面的可操作性判断即可,不需要纠结底层内存抽象概念:
- 只要可以直接对表达式本身使用取址符
&且编译不报错,对应的对象就拥有程序可访问的地址。注意不包括将表达式的值赋值给其他变量后再对新变量取址的情况。 - 唯一的标准特例是位域:位域属于左值,但C++标准明确规定不允许对位域直接取址,因为位域可能不占据字节对齐的独立内存位置。
二、看起来像Lvalue但实际不属于Lvalue的示例
以下是开发中最容易混淆的场景:
std::move()调用的返回结果:std::move(变量名)看起来指向一个已经存在的左值变量,实际返回的是右值引用,属于右值范畴,不是左值,不能直接取址。- 自定义类型的临时对象:比如
std::string("test")、struct A{}; A(),看起来是完整的类对象,甚至可以调用成员函数,但属于纯右值,不是左值。 this指针:很多开发者误以为this是指向当前对象的左值指针,实际this是指针常量,属于右值,无法执行&this取址操作。- 算术/逻辑运算的结果:比如
a + 1、a && b的返回值是临时生成的纯右值,看起来和操作数类型一致,但不属于左值。 - 后置自增/自减表达式的结果:比如
a++、a--返回的是运算前的临时值副本,属于纯右值,和返回左值的前置自增/自减完全不同。
三、核心场景C++ Lvalue示例清单
覆盖90%以上开发场景的左值示例如下:
- 所有已声明的变量名,无论是否带
const、volatile修饰,比如int a = 1中的a、const int b = 2中的b均为左值。 - 数组元素访问结果,比如
int arr[5];中的arr[2]是左值。 - 返回左值引用(
T&/const T&)的函数调用结果,比如std::string s;中的s[0](返回char&)、用户自定义函数int& get_val() {static int x; return x;}的调用结果get_val()均为左值。 - 类/结构体非静态数据成员的访问结果,比如
struct A {int x;}; A a;中的a.x是左值,即使成员带const修饰也不影响左值属性。 - 对指针的解引用操作结果,比如
int* p = &a;中的*p是左值。 - 字符串字面量,比如
"hello world",属于const char[N]类型的左值,是内置字面量中唯一的左值特例,可直接用&取址。 - 前置自增/自减表达式的结果,比如
++a、--a返回左值引用,属于左值。 - 赋值类表达式的结果,比如
a = b、a += 3的返回值为左值引用,属于左值。 - 逗号表达式的最终结果为左值时,整个逗号表达式属于左值,比如
(a++, b)中如果b是左值,整个表达式就是左值。 - 三目运算符的两个分支均为左值时,整个表达式结果为左值,比如
c > 0 ? a : b中a、b均为左值时,整个表达式可直接被赋值。
内容的提问来源于stack exchange,提问作者Theoretical Physics
相关产品推荐
相关产品推荐

