C++11 左值引用和右值引用、完美转发和引用折叠

一、左值与右值

1、最感性的认识

 

2、当然,左值也是可以在右边的

 3、左值是可以被修改的,右值不能

 4、当然取地址也是

 

生存周期一般左值会比右值的长

一般右值都计算时产生的无名临时对象,存在时间比较短

下面还有一种情况也要区分

 

二、左值引用和右值引用

左值引用:可以引用一个对象,有时候也可以绑定一个右值

右值引用:只能引用右值

1、左值引用

int a = 3;
int &p1 = a;  // 左值引用

左值引用右值,将引发异常

 但加上 const 就好了

 2、右值引用

不能把左值绑定到右值,但使用 move 可以把左值转换右值就可以绑定

例如1

 

例如2

 

例如3

 

好了,理解上边的知识

接下来到引用折叠规则

三、引用折叠

怎么说好呢

来一段代码看看

#include <iostream>
using namespace std;

using lRef = int&;   //左值引用
using rRef = int&&;	 //右值引用

int main(int argc, char **argv)
{
	is_lvalue_reference<lRef &>::value ?
		cout << "lRef &  左值引用" << endl :
		cout << "lRef &  右值引用" << endl;

	is_lvalue_reference<lRef &&>::value ?
		cout << "lRef && 左值引用" << endl :
		cout << "lRef && 右值引用" << endl;


	is_rvalue_reference<rRef &>::value ?
		cout << "rRef &  右值引用" << endl :
		cout << "rRef &  左值引用" << endl;

	is_rvalue_reference<rRef &&>::value ?
		cout << "rRef && 右值引用" << endl :
		cout << "rRef && 左值引用" << endl;


	return 0;
}

调试结果

上边就是引用折叠规则

看着懵

没关系

看下图

 

 

由上图应该可以理解引用折叠规则了

 可以看到只有都是右值引用的时候才是右值引用

当然只有一个右值引用的情况下自然而然也是右值引用

 

四、完美转发

完美转发是用来干嘛的呢

主要是用来

参数转发时

是左值传入还是右值传入

我们来一段测试代码

#include <iostream>
using namespace std;

template<typename T> 
void Fun1(T& v)
{
	cout << "左值引用调用" << v << endl;
}

template<typename T>
void Fun1(T&& v)
{
	cout << "右值引用调用" << v <<endl;
}

template<typename T>
void Fun(T&& v)
{
	Fun1(v);
}

int main(int argc, char **argv)
{
	int a = 3;

	Fun(a);

	return 0;
}

主函数里给 Fun 传入 a

根据上边知识 

a 是一个左值,看调试结果是调用哪一个重载版本 Fun1

调试结果:发现和预想中的一样

 

接下来,我们更改为右值传入

int main(int argc, char **argv)
{

	Fun(5);

	return 0;
}

调试结果

 这时,发现和想象中的不一样了

那么,为打目的我们要怎么做?

在 C++11 中提供了一个完美转发的函数 forward

还提供了一个 move 函数,用于把左值变右值的方法

forward 会根据引用折叠规则判定传入的是左值引用还是右值引用

好了,修改一下代码

template<typename T>
void Fun(T&& v)
{
	Fun1(forward<T>(v));
}

 再次调试结果

发现,达到目的啦

完美转发完整代码

 

#include <iostream>
using namespace std;

template<typename T> 
void Fun1(T& v)
{
	cout << "左值引用调用" << v << endl;
}

template<typename T>
void Fun1(T&& v)
{
	cout << "右值引用调用" << v <<endl;
}

template<typename T>
void Fun(T&& v)
{
	Fun1(forward<T>(v));
}

int main(int argc, char **argv)
{
	int a = 1;
	Fun(a);
	Fun(move(a));

	const int b = 2;
	Fun(b);
	Fun(move(b));

	Fun(5);

	return 0;
}

 调试结果

 

五、_End

/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值