1.所谓泛左值是指一个通过评估能够确定对象、位域或函数的标识的表达式。简单来说,它确定了对象或者函数的标识(具名对象)。
2.而纯右值是指一个通过评估能够用于初始化对象和位域,或者能够计算运算符操作数的值的表达式。
3.将亡值属于泛左值的一种,它表示资源可以被重用的对象和位域,通常这是因为它们接近其生命周期的末尾,另外也可能是经过右值引用的转换产生的。

从本质上说产生将亡值的途径有两种,
第一种是使用类型转换将泛左值转换为该类型的右值引用,比如:
Widget w1;
通过staic_cast强制转换:Widget&& w = static_cast
或者通过std::move():Widget&& w = std::move(w1);
第二种在C++17标准中引入,我们称它为临时量实质化,指的是纯右值转换到临时对象的过程。每当纯右值出现在一个需要泛左值的地方时,临时量实质化都会发生,也就是说都会创建一个临时对象并且使用纯右值对其进行初始化,这也符合纯右值的概念,而这里的临时对象就是一个将亡值。
struct X
{int value;
};
int main()
{int x = X().value;
}在上面的代码中,X()是一个纯右值,访问其成员变量value却需要一个泛左值,所以这里会发生一次临时量实质化,将X()转换为将亡值,最后再访问其成员变量value。还有一点需要说明,在C++17标准之前
临时变量是纯右值,只有转换为右值引用的类型才是将亡值。
通过代码进一步归纳下值类别:
#include
#include
#include
#include template
std::string type_to_string()
{
#if defined(_MSC_VER)std::string typeName{__FUNCSIG__};auto start = typeName.find_first_of('<', std::string(typeid(std::string).name()).size()) + 1;auto end = typeName.find_first_of('>');return typeName.substr(start, (end - start));
#elif defined(__clang__)std::string typeName{__PRETTY_FUNCTION__};auto start = typeName.find_first_of('=') + 2;auto end = typeName.find_first_of(']', start);return typeName.substr(start, (end - start));
#elif defined(__GNUC__)std::string typeName{__PRETTY_FUNCTION__};auto start = typeName.find_first_of('=') + 2;auto end = typeName.find_first_of(';', start);return typeName.substr(start, (end - start));
#endif
}//lvalue
template
inline constexpr bool is_lvalue = std::is_lvalue_reference_v;
//xvalue
template
inline constexpr bool is_xvalue = std::is_rvalue_reference_v;
//prvalue
template
inline constexpr bool is_prvalue = !(is_lvalue | is_xvalue);int a = 10;
int temp = 10;int& f(){return a;}
void g(){}
int&& h(){ return static_cast(temp);}void(&&g2)() = g;struct Person
{
int age;
static int widget;
};
//int Person::widget = 0;int main()
{//左值
//1. 普通变量
std::cout << std::boolalpha;
std::cout << "lvalue: " << is_lvalue << std::endl; // a is lvalue.//2. 函数
std::cout << "lvalue: " << is_lvalue << std::endl; // main() function is lvalue.//3. 成员变量
Person p;
std::cout << "lvalue: " << is_lvalue << std::endl; // p.age is lvalue.
std::cout << "lvalue: " << is_lvalue << std::endl; //Person::widget function is lvalue.//4. 字符类型的字面量
std::cout << "lvalue: " << is_lvalue << std::endl; // "hello world" is lvalue.
std::cout << type_to_string() << std::endl; // const char (&)[12] is lvalue.//5. 左值引用类型的函数返回值
std::cout << "lvalue: " << is_lvalue << std::endl; // f type: int(), f()->int& is lvalue.void(&gr)()=g;
//6. 函数不管怎么变都是左值
std::cout <() << std::endl; // "hello world" is lvalue.
std::cout <() << std::endl; // gr type: void*&)(), &g is lvalue.
std::cout << "lvalue: " << is_lvalue << std::endl; // &gr is lvalue.std::cout << type_to_string() << std::endl;//std::cout << "lvalue: " << is_lvalue << std::endl;////纯右值//1. 除字符串字面量意外的其他字面量
std::cout << "prvalue: " << is_prvalue << std::endl; //10 is prvalue.
std::cout << "prvalue: " << is_prvalue << std::endl; //true is prvalue.
std::cout << "prvalue: " << is_prvalue << std::endl; //nullptr is prvalue.//2. 函数返回值
std::cout << "prvalue: " << is_prvalue << std::endl; //main()->int is prvalue.//3. 临时对象
std::cout << "prvalue: " << is_prvalue << std::endl;//4. 取地址
std::cout << "prvalue: " << is_prvalue << std::endl;//5. lambda表达式[since C++20]
//std::cout << is_prvalue << std::endl;//这种形式的lamba也是个临时对象//将亡值
//1. std::move()
int x = 10;
std::cout << "xvalue: " << is_xvalue << std::endl;
std::cout << "xvalue: " << is_xvalue << std::endl;//2. static_cast
std::cout << "xvalue: " << is_xvalue(10)))> << std::endl;
std::cout << "xvalue: " << is_xvalue(x)))> << std::endl;//3. 函数范围值和为T&&类型
std::cout << "xvalue: " << is_xvalue << std::endl;//4. rvalue对象的非静态成员
Person p2;
std::cout << "xvalue: " << is_xvalue << std::endl;
std::cout << "xvalue: " << is_xvalue << std::endl;}