左值引用与右值引用的区别

定义:左值引用是对左值的引用。右值引用是对右值的引用。

功能差异:

  • 左值引用(避免对象拷贝)

    • 函数传参

    • 函数返回值(拷贝赋值函数)

  • 右值引用

    • 移动语义

    • 完美转发

左值和右值的区别

左值的特性:

  • 可以放在=的左边

  • 能够取地址

  • 具备名字(可以有引用)

左值举例:

  • 变量名

  • 返回值为引用的函数调用

  • 前置自增/前置自减

  • 赋值运算符或复合赋值运算

  • 解引用

int main()
{
// 先自增再赋值给i,再进行一个返回。所以++i这个表达式返回的还是i本身,可以取地址
int i=0;
++i=10;

//赋值运算符|复合赋值运算
(i=9)=100;
(i+=10)=100;

//解引用
int *num = new int(10);
*num=100;
return 0;
}

右值的特性:

  • 只能在=右边

  • 不能取地址

  • 不具备名字(不能有引用)

右值类型:

  • 纯右值(不具备标识符的临时对象或表达式)

    • 字面值

    • 返回非引用类型的函数调用

    • 后置自增/后置自减

    • 算术表达式/逻辑表达式

  • 将亡值:

    • 可以用来触发移动构造或者移动赋值构造,并进行资源转移。

    • 将亡值是一种特殊的纯右值,具有右值引用类型,可以进行修改和转移的对象。(因为只有右值引用类型才能触发移动构造或者移动赋值构造)。

    • move()主要用于将对象转换为右值引用,以便实现移动语义和资源的转移操作。

    • 将亡值是一种要被移动的右值,它允许对资源进行转移,以实现高效的资源管理。

移动语义

作用:对象赋值时,避免资源的重新分配。

实现:移动构造以及移动拷贝构造

STL应用:由于实现了移动语义,效率大幅增高。例如insert,erase。

完美转发

定义:函数模板可以将自己的参数可以完美地转发给内部调用的其他函数,其中完美是指不仅能够转发参数的值,还能保证被转发的参数左右值属性不变。

万能引用:通过引用的方式接收左右属性的值(T&&),使用万能引用可以保证正确的参数接收。

引用折叠规则:参数为左值或左值引用,T&&将转换为int &;参数为右值或右值引用,T&&将转换为int&&。

template<typename T>
void revoke(T &&t)
{
func(t);
}

revoke(static_cast<int&>(n));
int & &&t => int &t;

revoke(static_cast<int&&>(m));
int&& &&t => int && t;

revoke(n);
int && t => int & t;

std:forward<T>(v)T为左值引用,v将转换成T类型的左值;T为右值引用,v将转换为T类型的右值。

大杂烩

左值引用能否指向右值,右值引用能否指向左值?

  • const左值引用能指向右值,局限是不能修改这个值

  • 右值引用可以通过move()指向左值

  • 声明出的左值引用和右值引用是左值