首页 > 编程语言 > 详细

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

时间:2021-07-23 15:52:18      阅读:15      评论:0      收藏:0      [点我收藏+]

1.左值与右值

最感性的认识。
技术分享图片

当然,左值也是可以在右边的。
技术分享图片

左值是可以被修改的,右值不能。
技术分享图片

当然取地址也是。
技术分享图片

生存周期一般左值会比右值的长,一般右值都计算时产生的无名临时对象,存在时间比较短。

下面还有一种情况也要区分。
技术分享图片

2.左值引用和右值引用

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

右值引用:只能引用右值。

1左值引用示例

看以下代码,比较正常。

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

若左值引用右值将报错
技术分享图片

但加上const就可以引用了
技术分享图片

2右值引用示例

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

示例1
技术分享图片

示例2
技术分享图片

示例3
技术分享图片

理解了上边知识,接下来是引用折叠规则,

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;
}

调试结果
技术分享图片

这就是引用折叠规则。

这怎么理解呢,看下图
技术分享图片

可以看到只有都是右值引用的时候才是右值引用,当然只有一个右值引用的情况下自然而然也是右值引用。

这是就引用折叠。

4.完美转发

主要用于参数转发时是左值传入还是右转入
考虑以下代码

#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会根据引用折叠规则得出传入的是左值引用还是右值引用

接下来只需更改一下Fun函数,其他的不变

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;
}

调试结果
技术分享图片

5.结语

学无止境。
---End

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

原文:https://www.cnblogs.com/lvvou/p/15048361.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!