相信你遇到过不知道多少次rvalue
和lvalue
,但对于像glvalue
、xvalue
、prvalue
这样的词恐怕你听都没听过,但是要准确把我左值和右值的定义,他们也必须理解清楚。
expression
C++
中的所有表达式都是一个值,就像下面这样子的。
1 + 2; // 表达式;一个对象
3; // 表达式;一个对象
func(); // 表达式;一个对象
&func; // 表达式;一个指针
lvalue
左值
。能出现在赋值表达式左边的值,同时别被他名字骗了,它也能出现在赋值表达式的右边。
int n = 0;
n = 1; // n是左值
int m = n; // n是左值
int& func();
func() = 12; // func函数的返回值是左值
rvalue
右值
。只能出现在赋值表达式右边的值,它们分为xvalue
和prvalue
两种。
int n = 0; // 0是右值; prvalue
int m = std::move(n); // std::move(n)是右值 ; xvalue
prvalue
pure rvalue
的缩写,纯右值。C++03
之前的所有rvalue
都属于这一类,典型代表就是各种字面量
(literal
),比如:1
,'a'
……还有一般函数的返回值。
int func();
func(); // func函数的返回值是prvalue
xvalue
eXpiring value
的缩写,可以理解为快要死掉的值。C++11
中把左值
通过类型转换变成右值引用
时,使用move语义
时都会产生xvalue
。
int n = 0;
int m = static_cast< int&& >(n); // static_cast< int&& >(n)是xvalue
int&& func();
func(); // func函数的返回值是xvalue.
std::move(n); // xvalue
glvalue
generalized lvalue
的缩写,包括lvalue
和xvalue
。引入这么个概念是为了强调,具名右值引用虽然作为xvalue
,跟其他右值有着本质区别(那就是它可以像左值那样使用)这种现象。
struct A {
int m;
};
void print(A a)
{
std::cout<<a.m<<std::endl;
}
int main(int argc, char *argv[])
{
A a;
A&& ar = static_cast<A&&>(a);// ar就是具名右值
print(ar);
A aa;
ar = aa;
print(ar);
}