C++的引用折叠
引用折叠:创建引用的引用时(如模板参数、类型别名)会造成引用折叠,折叠规则如下:2.&&+&&->&&
1.
&+&->&
&&+&->&
&+&&->&
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(); }
例子:
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();
}
引用折叠了:i是普通int变量,普通左值按规则3,得到&
5是右值,没有引用折叠
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*类型:
另一个例子:
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&
进击的小🐴农