条款28:理解引用折叠

考虑如下代码:

template<typename T>
void func(T &&parem);

Widget widgetFactory();	// 返回右值的函数
Widget w;				// 变量(左值)
func(w);				// 调用func并且传入左值,T的推导类型为Widget&
func(widgetFactor());	// 调用func并且传入右值,T的推导类型为Widget

传递实参类型都为Widget,一个左值,一个右值,导致了针对模板形参T得出了不同的推导结果。决定万能引用是变成左值还是右值引用的机制,也是std::forward得以运作的机制。

C++中“引用的引用”是非法的:

int x;
auto& & rx = x; //错误!不可以声明引用的引用

当左值传递给万能引用时会发生下面的情况:

template<typename T>
void func(T &&parem);
func(w);

如果把T的推导类型(即Widget &)代码实例化模板,就得到如下结果:

void func(Widget& && param);

上述为引用的引用。由于万能引用param是左值初始化的,其推导结果类型应该是左值引用, 但是编译器进行了哪些操作从而有了如下的函数签名呢?

 void func(Widget &param);

答案为引用折叠,规则为:

如果任一引用为左值引用,则结果为左值引用,否则为右值引用

引用折叠是使std::forward得以运作的关键:

template<typename T>
void f(T &&fParam) {
	someFunc(std::forward<T>(fParam));	// 將fParam转发至somFunc
}

std::forward的任务为:当且仅当编码T中的信息表明传递给实参是个右值,对fParam(左值)实施到右值的强制类型转换

引用折叠发生的情况还有auto变量的类型生成:

Widget w;
auto&& w1 = w;

初始化w1的是个左值,因此auto的类型推导结果为Widget &。在w1声明中以Widget&带入auto,久产生如下代码:

Widget& && w1 = w;

引用折叠后会变成:

Widget & w1 = w;

第三种引用折叠的情况是生存和使用typedef和别名声明:

template<typename T>
class Widget {
public:
	typedef T&& RvalueRefToT;
}

假设我们用坐值引用实例化:

Widget<int &> w;

在Widget中以int&带入T的位置得到如下:

typedef int & &&RvalueRefToT;

引用折叠后为:

typedef int& RvalueRefToTl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值