1. 左值和右值
(1)两者区别:
①左值:能对表达式取地址、或具名对象/变量。一般指表达式结束后依然存在的持久对象。
②右值:不能对表达式取地址,或匿名对象。一般指表达式结束就不再存在的临时对象。
(2)右值的分类
①将亡值(xvalue,eXpiring value):指生命期即将结束的值,一般是跟右值引用相关的表达式,这样表达式通常是将要被移动的对象,如返回类型为T&&的函数返回值(如std::move)、经类型转换为右值引用的对象(如static_cast< T&& >(obj))、xvalue类对象的成员访问表达式也是一个xvalue(如Test().memberdata,注意Test()是个临时对象)
②纯右值(prvalue, PureRvalue):按值返回的临时对象、运算表达式产生的临时变对象、原始字面量和lambda表达式等。
2. 右值引用和左值引用
(1)右值引用和左值引用
①右值引用和左值引用都是属于引用类型。无论是声明一个左值引用还是右值引用,都必须立即进行初始化。
②左值引用是具名变量/对象的别名,右值引用是匿名变量/对象的别名。
③左值和右值是独立于它的类型的,即左右值与类型没有直接关系,它们是表达式的属性。具名的右值引用是左值,匿名的右值引用是右值。如Type&& t中t是个具名变量(最简单的表达式),t的类型是右值引用类型,但具有左值属性。而Type&& func()中的返回值(是个表达式)是右值引用类型,但具有右值属性(因为是个匿名对象)。

[表 2-1]引用类型分类表
3.std::forward与std::move
std::move是无条件的转为右值引用,而std::forward是有条件的转为右值引用,更准确的说叫做Perfect forwarding(完美转发),而std::forward里面蕴含着的条件则是Reference Collapsing(引用折叠)。
move 用于指明转移语义,常见于传参数和返回值。move 用于提示编译器,这里可以是转移语义,否则编译器会保守的使用复制语义。
—————————————————————避免拷贝耗资源——————————————————————-
4.C++测试代码
#include <iostream>
#include <vector>
#include <typeinfo>
void func(int& i)
{
std::cout<< __PRETTY_FUNCTION__ <<" : " << typeid(i).name()<<std::endl;
}
void func(int&& i)
{
std::cout << __PRETTY_FUNCTION__ << " : " << typeid(i).name() <<std::endl;
}
void func2(const int& i)
{
std::cout << __PRETTY_FUNCTION__ << " : " << typeid(i).name() <<std::endl;
}
void l_func(int &i)
{
std::cout << __PRETTY_FUNCTION__ << " : " << typeid(i).name() <<std::endl;
}
void r_func(int&& i)
{
std::cout << __PRETTY_FUNCTION__ << " : " << typeid(i).name() <<std::endl;
}
//__PRETTY_FUNCTION__是linux宏
template<class T>
void wrapper(T&& x)
{
func(std::forward<T> (x)); //forward完美转发,有条件转为右值引用
func(std::move(x)); //move无条件的转为右值引用
}
int main()
{
int a =10;
const int c = 20;
std::cout<< "##########左值与右值 Test##########"<<std::endl;
func(a); //非常量左值
func(20); //非常量右值
//l_func(10); //10不可以作为一个左值传递
//r_func(a); //a不可以作为一个右值传递
//int &&d = 20; //常量右值
//
std::cout<< "##########forward与move Test##########" <<std::endl;
wrapper(a);
wrapper(20);
std::cout<< "##########常引用 Test##########" <<std::endl;
//常引用万能类型,用于拷贝语义
func2(a); //非常量左值
func2(c); //常量左值
const int& d = 20; //常量右值
func2(20); //非常量右值
std::cout<<"Test d : "<<d<<std::endl;
return 0;
}
运行结果:

本文前两段来自 : 作者 : 浅墨浓香 | 链接 : https://www.cnblogs.com/5iedu/p/7698710.html
本文第三段来自 : 作者:蓝色 | 链接:https://www.zhihu.com/question/34544004/answer/59104471