完美转发是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。
函数模板在向其他函数传递自身形参时,如果相应实参是左值,它就应该被转发为左值;如果相 应实参是右值,它就应该被转发为右值。这样做是为了保留在其他函数针对转发而来的参数的左右值属性进行不同处理(比如参数为左值时实施拷贝语义;参数为右值时实施移动语义)。
std::forward完美转发标志
完美转发是为了解决传递参数时的临时对象(右值)被强制转换为左值的问题
forward会保持实参属性
实现
//目标/靶机
void target(int& x){cout << "左值目标" << endl;}
void target(int&& x) { cout << "右值目标" << endl; }
void target(const int& x) { cout << "const左值目标" << endl; }
void target(const int&& x) { cout << "const右值目标" << endl; }
template<class T>
void transferStation(T&& t){target(std::forward<T>(t));}
int main()
{
transferStation(10);//右值目标
int a;
transferStation(a);//左值目标
transferStation(std::move(a));//右值目标
const int b = 1;//const int b在C++11中默认是左值
transferStation(b);//const左值目标
transferStation(std::move(b));//const右值目标
return 0;
}
图像理解
总体思路
该段代码实现思路
没有对应目标函数
transferStation("abc");//报错没有可调用函数
此时经过forward检查后发现没有能使用的目标函数就会报错
区分万能引用标签&&和右值引用
//万能引用&&
template<class T>
void transferStation(T&& t){target(std::forward<T>(t));}
//右值引用&&
void transferStation(int&& t) { cout << "右值引用&&" << t << endl; }
int main()
{
transferStation<int>(10);//右值目标
transferStation(10);
return 0;
}
对不懂forward<T>(t)的解释
class A1
{
public:
void Print()
{
cout << "无模板匿名对象" << endl;
}
private:
//...
};
template<class T>
class A2
{
public:
void Print()
{
cout << "有模板匿名对象" << endl;
}
private:
//...
};
int main()
{
A1().Print();//无模板匿名对象
A2<int>().Print();//有模板匿名对象
return 0;
}
结果:
结论
使用完美转发时:有template<T>需要改函数自己推演类型,函数中的&&为万能引用
使用右值引用时:不需要自动推演,为固定模式此时&&为右值引用