完美转发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
void f(const string& s){
cout <<"左值:"<<s<<endl;
}
void f(string&& s){
cout <<"右值"<<s<<endl;
}
void g(const string& s){
f(s);
}
void g(string&& s){
f(s);
}
int main(){
// 右值
g(string("hello1"));
// 左值
string s1("hello2");
g(s1);
}这段代码,我们希望让右值调用右值的重载函数f,左值调用左值的重载函数f,但最后结果均调用了左值重载函数
这是因为在函数g中,s本身是一个局部变量,拥有地址,是一个左值
这时候我们需要进行类型转换
std::forward
我们当然可以使用static_cast<>()来进行转换,但是这里可以使用forward<>()函数进行转换,结合函数模板,使得代码更加方便易读
1
2
3
4
template<class T>
void g(T&& s){
f(forward<T>(s));
}这里在形参列表中的T&& s被称为万能引用或转发引用
它既可以绑定左值也可以绑定右值,会在实例化时根据传入参数类型自动推导成对应类型
T的类型取决于传入的是左值还是右值
- 左值:T被推导为实参类型的引用
- 右值:T被推导为实参类型的非引用
forward函数实现了一个类型转换
- 若传入实参是右值,则forward函数会返回一个右值引用
- 若传入实参是左值,则函数模板T会被替换为该类型的引用,但此时会出现引用的引用(&&&),这时遵循引用折叠规则,得到类型的左值引用
即除了右值引用的右值引用被折叠为右值引用外,其余的只要有左值引用,就会被折叠为左值引用