现代C++(1):万能引用与完美转发

阅读此文章之前,默认读者会C++的基础语法和模板

目录

导论

1.万能引用(Universal Reference)

1.1引用折叠(Reference Collapsing)

2.完美转发(Perfect Forwarding)

案例:


导论

什么是万能引用完美转发

研究这个问题之前,我们先搞清楚为什么需要这些新的特性。

当一个左值传递给一个函数时,参数会以左值引用的方式进行传递;

当一个右值传递给一个函数时,参数会以右值引用的方式进行传递。

那么什么是左值右值

  • 左值(Lvaule)指表达式结束后依旧存在的对象。

  • 右值(Rvalue)指表达式结束后便销毁的临时对象。

左值引用就是给左值取别名,实际上指向了同一片内存空间。

右值引用就是给右值取别名,实际上也指向了同一片内存空间。

那么区别在哪里?

右值有着表达式结束后对象便销毁的特性,但如果我们使用了右值引用,

那么编译器便不会立刻销毁对应的空间

如此为了实现某一个要求,便有了万能引用与完美转发。

1.万能引用(Universal Reference)

万能引用便是在左值引用和右值引用的基础上,利用模板自动类型推导的特性,自动判断传入的是左值引用还是右值引用。

语法:T&& Val

注意: 

​
template<typename T> //函数模板
void f( T&& val); // 这里T的类型需要推导,所以是万能引用

template<typename T>  //类模板
class Ttpe
{
	Type(Type&& val);  // Type是一个特定的类型,不能类型推导,所以&&表示具体的右值引用  
};

只有当发生自动类型推导时,T&&才是万能引用

1.1引用折叠(Reference Collapsing)

由于万能引用是自动类型推导,便自然衍生出了一个特性——引用折叠。

概念:

由于存在T&&这种未定的引用类型,当它作为参数时,有可能被一个左值引用或右值引用的参数初始化,这是经过类型推导的T&&类型,相比右值引用(&&)会发生类型的变化,这种变化就称为引用折叠。(《深入应用C++11-代码优化与工程级应用》 --- 祁宇 P68 )

如果两个引用中至少其中一个引用是左值引用,那么折叠结果就是左值引用;否则折叠结果就是右值引用。

规则:

内层引用类型外层引用类型结果
T&&T&
T&&&T&
T&&&T&
T&&&&T&&

2.完美转发(Perfect Forwarding)

当我们使用了万能引用,但需要转发参数给其他函数时,会丢失引用性质,由此便有了完美转发。

C++11提供了完美转发函数。它可以在模板函数内给另一个函数传递参数时,将参数类型保持原本状态传入。

语法: std::forward<T> 

​
template<class T>
void func(T&& obj){
    _func(std::forward<T>(obj));
}


案例:

C++标准模板库(STL)就有完美的运用万能引用与完美转发的例子。

为了方便理解与运用,这里我用自制的循环队列来讲解。

​
#include <iostream>
using namespace std;

template<class T>
struct SqQueue
{
	T data[10] = { };
	int front, rear;
	int size;

	SqQueue()
	{
		front = rear = size = 0;
	}

	template<class... V>
	void emplace(V&&... Val)
	{
		new (&data[rear]) T(forward<V>(Val)...);
		this->rear = (this->rear + 1) % Max;
		size++;
	}
};

我们只将重点放在这里的emplace函数上。

此函数的用意便是在队列的“rear”也就是尾节点内插入一个全新的数据。

template<class… V1>表示这是一个函数模板,

”表示可以有多个参数,

形参列表里就是上面讲的万能引用,

forward<V>(Val…)完美转发,可以在模板函数内给另一个函数传递参数时,将参数类型保持原本状态传入

new (指针) T (args)相当于对已有地址进行new的初始化,强行调用构造函数。

由此,便可直接在使用时emplace函数时直接构造一个对象,而省去了拷贝操作,降低了时间复杂度。和STL里的emplace同理,这便是万能引用与完美转发的具体运用。

本人才疏学浅,如有错误请指正,感激不尽!

以上都是群内巨佬——三色牌告诉我的,有问题可以在群里找他,我是菜鸡

群号:762514085

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值