C++ 11 万能引用

引用折叠规则

  • T& & -> T&
  • T& && -> T&
  • T&& & -> T&
  • T&& && -> T&&

小结:只有右值引用的右值引用会折叠成右值引用,其余情况都是折叠成左值引用

完美转发

某些场景下有参数转发的需求:最理想的情况下是外层的Wrapper(下面的 factory 函数)就像不存在一样而内层函数就像直接被调用一样
调用 wrapper 时传递的是左值,内层函数被调用时得到的就是左值;调用 wrapper 时传递的是右值,内层函数被调用时得到的就是右值。

万能引用

以引用形式作为参数的函数,一般只能匹配左值或者只能匹配右值

1
2
int foo(int & i);  // 只能接受左值引用参数
int foo(int && i); // 只能接受右值引用参数
  • 若是想以左值引用形式接受右值引用参数,则必须将参数声明为 const 的左值引用;此时若是有多个形参,针对每个形参都要重载 const 和非 const 版本,是很复杂的排列组合问题,且无法触发移动语义。
  • 此时需要万能引用:以一种形式的参数形式接受左值引用和右值引用;万能引用的两个前提条件:模板形式;&& 型参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<typename T, typename Arg>
shared_ptr<T> factory(Arg && arg) {
return shared_ptr<T>(new T(std::forward<Arg>(arg)));
}

class CTemp{
int data;
public:
CTemp(int& arg) : data(arg){
cout << "CTemp(int& arg) called\n";
}
CTemp(int&& arg) : data(arg){
cout << "CTemp(int&& arg) called\n";
}
};

int main() {
int value = 1;
auto p1 = factory<CTemp>(value);
auto p2 = factory<CTemp>(2);

return 0;
}


运行结果

1
2
CTemp(int& arg) called
CTemp(int&& arg) called

说明 factory 函数将接收到的参数“完美”转发(不改变参数的左右值属性)给内层函数

参考