《Effective Modern C++》学习笔记之条款二十八:理解引用折叠

本文详细解析了C++中引用折叠的概念及应用,包括模板实例化、auto变量型别生成等场景,并通过具体示例说明了引用折叠如何影响参数类型推导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面我们说过,形参为万能引用型别时,将根据实参的型别来决定最终param的型别:

template<class T>
void func(T&& param) {
    // do something
}

Widget w;
func(w);        // w为左值,T为Widget&,param为Widget&

func(Widget()); // 实参为右值,T为Widget,param为Widget&&

之所以会有上面结果的推导结果,就是因为引用折叠的存在,同样,std::forward中也深刻践行了引用折叠,引用折叠的规则如下:

如果任一引用为左值引用,则结果为左值引用,否则(即两个皆为右值引用)结果为右值引用。

引用折叠出现的语境有四种,分别为模板实例化、auto变量的型别生成、typedef和别名声明、decltype。

模板实例化和auto变量的型别生成技术细节上其实是一样的,因为auto型别推导和模板型别推导在本质上就是一模一样的。

模板实例化

template<typename T>
void func(T&& param);   // 模板函数

Widget widgetFactory(); // 返回右值的工厂函数

Widget w; // 左值变量

// 实参为左值,T被推导为Widget&(左值引用),所以param的推导结果为Widget& &&,即Widget&
func(w); 

// 实参为右值,T被推导为Widget(右值),所以param的推导结果为Widget&&,即Widget&&
func(widgetFactory());

auto变量的型别生成

Widget w; // 左值变量

// auto型别为Widget&,w1为Widget& &&,即Widget& 
auto&& w1 = w;
// 以右值初始化w2,auto被推导为Widget,所以w2为Widget&&型别
auto&& w2 = widgetFactory();

生成和使用typedef和别名声明

假设我们有个类模板Widget,内嵌一个右值引用型别的typedef:

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

再假设我们使用左值引用型别来实例化该Widget:

Widget<int&> w;

在Widget中以int&代入T的位置,则得到如下的typedef:

 typedef int& && ReturnValue;

引用折叠又将其简化为:

 typedef int& ReturnValue;

decltype

如果在分析一个涉及decltype的型别过程中出现了引用的引用,则引用折叠会将其简化掉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chiang木

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

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

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

打赏作者

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

抵扣说明:

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

余额充值