C++ 引用折叠和右值引用参数

3 篇文章 0 订阅

假定有一个模板如下

tempalte<typename T> void f(T&&);

如果有一个i为一个int对象,那么我们可能认为类似f(i)这样的调用是不合法的,因为通常不能将右值引用绑定到一个左值上:

int i = 0;
f(i);//向一个右值引用形参传入一个左值实参,是否正确?

事实上,C++在正常绑定规则外定义了两个例外规则允许这种绑定。这两个例外规则是move标准库设施正确工作的基础。

  • 第一个例外规则影响右值引用参数的推断如何进行:当将一个左值传递给函数的右值引用参数,且此右值引用指向模板类型参数(如上面的T&&)时,编译器会推断模板类型参数为实参的左值引用类型。 因此当调用f(i)时,编译器推断T的类型为int&而不是int。

  • 第二个例外绑定规则引用折叠如果间接创建一个引用的引用,则这些引用形成了折叠。在几乎所有情况下,引用会折叠成一个普通的左值引用类型。新标准中,折叠规则扩展到右值引用。只有在一种特殊情况下,引用会折叠成右值引用:右值引用的右值引用。

一个给定类型X按引用折叠规则折叠后的类型:

类型折叠后
X& &、X & && 、X && &X &
X && &&X &&

按上述规则,f可能会有如下实例化结果:

void f<int &>(int & &&);

f的参数是T&&,且T为int &,因此T&&是 int & &&,根据引用折叠规则,会折叠成int&。因此,虽然f接受一个右值引用参数,但调用依旧会用一个左值引用类型实例化f:

void f<int &>(int &);

总结上述两个规则导致的结果:

  • 如果一个函数参数是一个指向模板类型参数的右值引用(如 T&&),则它可以被绑定到一个左值
  • 如果实参是一个左值,推断出的模板实参将是一个左值引用,且函数参数将被实例化为一个左值引用参数(T&)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值