参考
参考
左值是一个引用内存位置的表达式,它允许我们通过 & 运算符获取该内存位置的地址。
纯右值 prvalue 是没有标识符、不可以取地址的表达式,一般也称之为“临时对 象
返回非引用类型的表达式
如 x++、x + 1
除字符串字面量之外的字面量如 42、true
将亡值:
隐式或显式调用函数的结果,该函数的返回类型是对所返回对象类型的右值引用
static_cast<int&&>(7);
std::move(7);
类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式是xvalue
struct As
{
int i;
};
As&& f(){
return As();
}
int main()
{
f().i;
return 0;
}
#include <iostream>
#include <type_traits>
void reference(int& v) { std::cout << "left" << std::endl; }
void reference(int&& v) { std::cout << "right" << std::endl; }
// T类型需要被推导,所以v的类型可能是左引用类型或右引用类型,但v本身是一个左值;
template <typename T>
void Func(T&& v) {
std::cout << std::is_lvalue_reference<decltype(v)>::value << ","
<< std::is_lvalue_reference<T&&>::value << std::endl;
std::cout << std::is_rvalue_reference<decltype(v)>::value << ","
<< std::is_rvalue_reference<T&&>::value << std::endl;
// 经过坍缩性/引用折叠,i:类型T的lvalue被推导为T&,v类型为int&, 1:
// 类型T的rvalue被推导为T,v类型为int&&, 但v本身是一个左值,只能绑定到左引用
// 若想绑定到右引用,则需要std::move(v)将v左值转换为右值;
reference(v);
reference(static_cast<T&&>(v)); // T&&可能是左引用或右引用
reference(std::move(v));
}
template <typename T>
void Forward(T&& v) {
// std::forward保留原来的左值性或右值性,相应的函数就会正确调用
reference(std::forward<T>(v));
}
int main() {
int i = 0;
Func(i); // i是一个左值
std::cout << "----------" << std::endl;
Func(1); // 1是一个右值(纯右值)
std::cout << "----------" << std::endl;
Forward(i);
Forward(1);
}