值类型是一个古老的概念,早在C++98就存在了,但在C++11之前这些都无关紧要,随着C++11右值引用的产生值类型也被赋予了新的含义。
但问题是C++11并未给出清晰的定义,比如在C++11的标准文档中,左值的概念只有一句话:“指定一个函数或一个对象”,这样的描述显然是不清晰的,问题直到C++17才得以解决。
表达式首先被分为泛左值和右值,其中泛左值又被分为左值和将亡值,右值被分为将亡值和纯右值,接下来逐一区分这些概念。
- 泛左值是指一个通过评估能确定对象、位域或函数的标识的表达式,简单来说它确定了对象或函数的标识(具体对象)
- 纯右值是通过评估可以用于初始化对象和位域,或者能够计算运算符操作数的值的表达式
- 将亡值是泛左值的一种,它表示资源可以被重用的对象和位域,通常这时因为它们接近其生命周期的末尾,另外也可能是经过右值引用的转换产生
- 左值是指非将亡值的泛左值
- 右值包含了纯右值和将亡值
左值就是传统意义上的左值,纯右值就是传统意义上的右值,问题是将亡值如何去理解,下面介绍将亡值产生的情景。
- 类型转化(将泛左值转化为该类型的右值引用)
static_cast<T&&>(val);
- 临时量实质化(纯右值转换到临时对象的过程)C++17引入
struct X{int a;
};
int main(){int b=X().a;
}
x()是一个纯右值,访问其成员变量需要一个泛左值,所以这里发生了一次临时量实质化,将x()转化为将亡值,最后再访问其成员变量。
需要注意的是C++17标准之前临时变量是纯右值,只有转化为右值引用的类型才是将亡值。