左值和右值
可以将表达式分类为下列其中一个值类别:
右值包括虚值和纯右值。 L值和x值可以称为泛型值。
- lvalue(左值)
- 如果表达式未
const限定,那么表达式可以出现在赋值表达式的左侧。
Xvalue
要到期的 rvalue 引用。
(Prvalue)
rvalue-
非xvalue
表达式 ,仅出现在赋值表达式的右侧。
右值包括虚值和纯右值。 L值和x值可以称为泛型值。
备注信息:
- 班级
(prvalue)
右值可以是 cv 限定的,但不是类的
(prvalue)
右值不能具有 cv 限定资格。 - 左值
和右值
可以是不完整类型,但右值
(纯右值)
必须为完整类型或 void类型。
对象是可以检查并存储到其中的存储区域。 左值
或x值
是指向此类对象的表达式。 lvalue 不一定允许修改它指定的对象。 例如,
除非存在合适的赋值运算符
。
或x值
是指向此类对象的表达式。 lvalue 不一定允许修改它指定的对象。 例如, const 对象是无法修改的 lvalue。 术语 可修改的 lvalue 用于强调 lvalue 允许更改和检查指定的对象。 以下对象类型的 Lvalues 是不可修改的 lvalues:- 数组类型
- 不完整的类型
const限定类型- 其成员之一符合
const类型的结构或并集类型
除非存在合适的赋值运算符
。
C将函数标识符定义为具有函数类型的表达式。 函数指示符与对象类型或 lvalue 不同。 它可以是函数的名称,也可以是取消引用函数指针的结果。 C语言在处理函数指针和对象指针时也有所区别。
返回左值引用的函数调用是左值。 表达式可以产生左值、
瞬时值
、
(纯右值)
右值,也可以不产生任何值。 
某些
内置
运算符需要左值作为部分操作数。 下表列出了这些操作程序及其用法的其他约束。
内置
运算符需要左值作为部分操作数。 下表列出了这些操作程序及其用法的其他约束。| 运算符 | 要求 |
|---|---|
| & (unary) | 操作数必须是左值。 |
| ++ -- | 操作数必须为可修改的左值。 这适用于前缀和后缀表单。 |
| = += -= *= %= <<= >>= &= ‸= |= | 左操作数必须是可修改的 lvalue。 |
例如,所有赋值运算符都对其右操作数求值,并将该值赋给其左操作数。 左操作数必须是可修改的 lvalue。
地址运算符 (
&) 需要 lvalue 作为操作数,而增量 (++) 和减量 (--) 运算符需要可修改的 lvalue 作为操作数。 以下示例显示了表达式及其相应的 lvalues。| 表达式 | lvalue(左值) |
|---|---|
x = 42 |
x |
*ptr = newvalue |
*ptr |
a++ |
a |
f() |
对 f() 的函数调用 |

- 调用返回类型为 rvalue 引用类型的函数的结果
- 强制类型转换为 rvalue 引用
- 通过 xvalue 表达式访问的非引用类型的非静态数据成员
- 一个指向成员访问表达式的指针,其中第一个操作数是 xvalue 表达式,第二个操作数是指向成员类型的指针
int a;
int&& b= static_cast<int&&>(a);
struct str{
int c;
};
int&& f(){
int&& var =1;
return var;
}
str&& g();
int&& rc = g().c;
在此示例中, rvalue 引用 b 的初始化方法是 xvalue ,因为它是强制转换为 rvalue 引用的结果。 对函数 f() 的调用会生成 xvalue ,因为此函数的返回类型为 int&& 类型。 rvalue 引用 rc 的初始化方法是 xvalue ,因为它是通过 xvalue 表达式访问非静态非引用数据成员 c 的表达式。

当GNU C语言扩展启用时,复合表达式、条件表达式和强制转换可以作为左值,前提是其操作数是左值。
如果序列中的最后一个表达式是 lvalue ,那么可以指定复合表达式。 以下表达式等效:
(x + 1, y) *= 42;
x + 1, (y *=42);地址运算符可以应用于复合表达式,前提是序列中的最后一个表达式是 lvalue。 以下表达式等效:
&(x + 1, y);
x + 1, &y;如果条件表达式的类型不是空的,并且其 true 和 false 的分支都是有效的 lvalue ,那么条件表达式可以是有效的 lvalue。 如果操作数是 lvalue ,那么强制转型是有效的 lvalue。 主要限制是不能使用左值转换后的地址。 
