[C++] 万能引用+引用折叠+完美转发

万能引用/通用引用(universal reference)

C++11增加了右值的概念,在模板中,可以用&&来表示右值引用,也可以用&&来表示万能引用。
1.如果重载了模板函数,一个参数是左值引用,一个参数是右值引用,那传入左值或者右值时会自动推导调用的函数模板。
2.如果只有一个模板函数,参数的写法是右值引用,此时传入左值或者右值都会调用这个模板函数。
因为这里的&&代表的是万能引用。

引用折叠

万能引用的实现原理是引用折叠,即模板函数的参数是 T&&,T的类型可以是int&或者int&&,T展开就是int& &&,或者int&& &&,此时发生引用折叠,左值引用还是折叠成左值,右值引用还是右值引用。

完美转发(std::forward)

不论函数的形参是左值引用还是右值引用,在传入函数后,在函数中再传入一个函数时,参数会丢失左值右值信息,在新的函数中会被视为左值。
为了保护参数的左值或者右值属性,就有了完美转发(std::forward<>())。

它的实现原理大概是:

Tempalte <typename T>
std::forward(typename std::remove_reference<T>::type& arg)
{
    static_cast<T&&>(t);
}
#include <iostream>

using namespace std;

#define _STD_FORWARD_USED_

template <typename T>
void Print(T& t)
{
        cout << "Print param is lr." << endl;
}

template <typename T>
void Print(T&& t)
{
        cout << "Print param is rr." << endl;
}

template <typename T>
void Test_Func(T&& t) 
{
//当模板的参数出现&&时,他可能是右值引用,也可能是万能引用。
        cout << "Test_Func" << endl;
#if defined(_STD_FORWARD_USED_)
        Print(std::forward<T>(t)); 
        //当使用std::forward<>()时,形参t保留了左值或者右值的属性。
        //因为保留了参数的初始属性,这就是[完美转发]。
#else
        Print(t); 
        //当不使用std::forward<>()时,形参t被转换成了左值。
#endif
}

int GetIntNum()
{
        return 1;
}
int main()
{
        int i = 9;
        int &li = i;
        int&& ri = GetIntNum();


        Test_Func(i);
        Test_Func(li);
        //这里有参数折叠,我们传入的是ing&,即T是int&,
        //此时实参列表式 int & &&,参数折叠为左值引用:int&。
        
        Test_Func(GetIntNum());
        //这里有参数折叠,我们传入的是右值,即T是右值引用int&&,
        //此时实参列表式 int && &&,参数折叠为右值引用:int&&。
}

输出结果:


        ->Not defined _STD_FORWARD_USED_
        * Test_Func
        * Print param is lr.
        * Test_Func
        * Print param is lr.
        * Test_Func
        * Print param is lr. 
        ->defined _STD_FORWARD_USED_
        * Test_Func
        * Print param is lr.
        * Test_Func
        * Print param is lr.
        * Test_Func
        * Print param is rr.
        -->在defined _STD_FORWARD_USED_的基础上,注释void Print(T& t),仅保留void Print(T&& t)也是可以的。
        -->因为仅用&&函数时,&&就从右值引用,变成了万能引用。

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值