C++的引用折叠

引用折叠:创建引用的引用时(如模板参数、类型别名)会造成引用折叠,折叠规则如下:
1.
&+&->&
&&+&->&
&+&&->&

2.&&+&&->&&

3.左值(非引用)+&&(模板形参的)->&,实际上是:编译器会自己在模板形参类型前加&,这样就变成了:&+&&,依据前面的规则还是会折叠为&。
注意:第3种情况只适用于&&形参的模板函数,不适合普通函数!
例子:
template<typename T> T ff(T&& x){    return x;}int fff(int &&x){    return x;}int main(){    int i=1;    cout<<ff(i);    cout<<fff(i);    getchar();}

其中fff(i)的调用是错误的!因为传递了一个左值给一个参数为右值引用的函数。ff(i)的调用是正确的,通过引用折叠,实际调用的函数是int ff(int&);

 

例子:

 

template<typename T> T ff(T&& x){
    return x;
}
int main()
{
    int i=1;
    int &j=i;
    int&& k=move(i);
    int p[10];
    cout<<ff(i);
    cout<<ff(5);
    cout<<ff(p);
    cout<<ff(j);
    cout<<ff(move(i));
    getchar();
}

C++的引用折叠

引用折叠了:i是普通int变量,普通左值按规则3,得到&

 C++的引用折叠

 

5是右值,没有引用折叠

 

C++的引用折叠

 

 

 p为int [10]类型,但这里由于符合上面第三条,加&得到int (&)[10],即一个int[10]数组的引用的类型。然后进行引用折叠:int (&)[10]+&&->int(&)[10],还是自己。

如果把函数改成这样:

template<typename T> T ff(T x){
    return x;
}
int main()
{
    int i=1;
    int &j=i;
    int&& k=move(i);
    int p[10];
    cout<<ff(i);
    cout<<ff(5);
    cout<<ff(p);
    cout<<ff(j);
    cout<<ff(move(i));
    getchar();
}

即f的参数不再是右值引用,那么就不存在引用折叠问题了,并且数组p传入f函数时,会自动转为int*类型:

 C++的引用折叠

 另一个例子:

typedef const int T;
typedef T& TR;
typedef T&& TRR;

void JudgeType()
{
    cout << "lvalue_ref_type?: " << is_lvalue_reference<TR>::value << endl;  // 1
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TR>::value << endl;  // 0

    cout << "lvalue_ref_type?: " << is_lvalue_reference<TR&>::value << endl; // 1
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TR&>::value << endl; // 0

    cout << "lvalue_ref_type?: " << is_lvalue_reference<TR&&>::value << endl; // 1
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TR&&>::value << endl; // 0

    cout << "lvalue_ref_type?: " << is_lvalue_reference<TRR>::value << endl;  // 0
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TRR>::value << endl;  // 1

    cout << "lvalue_ref_type?: " << is_lvalue_reference<TRR&>::value << endl; // 1
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TRR&>::value << endl; // 0

    cout << "lvalue_ref_type?: " << is_lvalue_reference<TRR&&>::value << endl; // 0
    cout << "rvalue_ref_type?: " << is_rvalue_reference<TRR&&>::value << endl; // 1
}

int main()
{
    JudgeType();
    system("pause");
}

 

 

一个暂时不懂的问题:

template<typename T> T ff(T&& x){
    return x;
}
template<typename T> T ff(const T& x){
    return x;
}
int main()
{
    int i=1;
    int& j=i;
    const int k=1;
    const int& l=i;
    cout<<ff(i);//调用ff(T&&)并折叠为T(&):符合左值(非引用)+&&,先加&,变成&+&&->&
    cout<<ff(j);//调用ff(T&&)并折叠为T(&):符合&+&&->&
    cout<<ff(5);//调用T(&&)
    cout<<ff(k);//调用T(const T&)
    cout<<ff(l);//调用T(const T&)
    getchar();
}

目前我只能认为只要能匹配&&的(通过引用折叠匹配的也算),都去匹配&&版本了。。

带const的都匹配不了&&,只能匹配const T&

 

 

原文链接: https://www.cnblogs.com/FdWzy/p/12439362.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++的引用折叠

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/333850

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午9:23
下一篇 2023年3月1日 下午9:23

相关推荐