【C++11】三大神器之——右值、移动语义、完美转发

前言

如果你还不知道C++11引入的右值、移动语义、完美转发是什么,可以阅读这篇文章;如果你已经对这些知识了如指掌,也可以看看有什么可以补充~😏

一、右值

值类别vs变量类型

在正式认识右值之前,我们要先区分值的类别和变量类型:

  • (value) 变量 (variable) 是两个独立的概念。值不一定拥有变量名(如表达式:i + j + k)。
  • 值只有类别(category) 之分,而变量只有类型(type)之分。

值类别可以被划分左值右值

那什么是左值和右值呢?左值是能被取地址、不能被移动的值。右值是表达式中间结果/函数返回值(可能拥有变量名,也可能没有)。

有一个可以区分左值和右值的便捷方法:看能不能对表达式取地址,如果能,则为左值,否则为右值。

C++11扩展了右值的概念,将右值分为了纯右值和将亡值,但本文不作讨论。

如下的示例将帮助我们区分左值和右值:

int i = 3;       // i是左值,3是右值
int j = i+8;    // j是左值,i+8是右值
char a = getCh();   // a是左值 ,getCh()的返回值是右值(临时变量)
左值引用、右值引用、常引用

在以前的文章中,我们曾经讨论过左值引用和常引用的区别。在本篇文章中,我们需要进一步系统的了解它们三者之间的关系。

引用类型 可以分为两种:

  • 左值引用:用&符号引用左值(但不能引用右值),
  • 右值引用:用&&符号引用右值(可以移动左值)。

在C++11中,因为增加了右值引用(rvalue reference)的概念,所以C++98中的引用都称为了左值引用(lvalue reference)。

使用方法如下所示:

int&& a = 3;         // 3是右值,a是右值引用
int b = 8;               // b是左值
int& bb = b;			//bb是左值引用
int&& c = b + 5;   //  b+5是右值,c是右值引用
AA&& aa = getTemp();   // getTemp()的返回值是右值(临时变量)

左值引用十分常见,我们知道是给变量取个别名,但是引入右值引用的意义是什么呢?(将在下文中解答)

在上述的代码中,getTemp()的返回值本来在表达式语句结束后,其生命也就该终结了(因为是临时变量),而通过右值引用重获了新生,其生命周期将与右值引用类型变量aa的生命周期一样,只要aa还活着,该右值临时变量将会一直存活下去。

在下面的代码中将帮助我们区分左值引用和右值引用:

void func(T& a);//1,参数是左值
void func(T&& a);//2,参数是右值
//T类型的变量
T var;
T& rvar1 = var;//正确,rvar1是左值
T& rvar1 = T{
   };//错误,左值引用不能引用右值
T&& rvar2 = T{
   };//正确,rvar2是右值
T&& rvar2 = var;//错误,右值引用不能引用左值
T&& rvar2 = std::move(var);//正确,可以通过std::move()将左值转为右值引用

func(var);//进入1,a是左值
func(T{
   });//进入2,a是右值
func(rvar1);//进入1,a是左值
func(rvar2);//进入1,rvar2是右值引用但a是左值

可以看出:

  • 左值引用变量rvar1在初始化时,不能绑定右值T{}
  • 右值引用变量rvar2在初始化时,不能绑定左值var,但是可以通过std
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白还在写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值