目录
2.完美转发的含义:函数参数传递的过程中,避免拷贝移动的操作,函数参数的左值性和右值性保持不变,也就是参数的类型和属性不发生变化
一.完美转发
1.转发的含义:就是函数参数的转发。
2.完美转发的含义:函数参数传递的过程中,避免拷贝移动的操作,函数参数的左值性和右值性保持不变,也就是参数的类型和属性不发生变化
3.函数参数传递的方式
4.实现完美转发
实现完美转发需要C++的三种技术
1.函数模板
2.引用折叠
3.forward<T> = static_cast<T&&>()
下面就这三种技术来实现完美转发,结合C++make_开头的工厂函数我们来实现自定义简单的工厂函数
#include <iostream> using namespace std; struct _person { _person(string&) { cout << "左值" << endl; } _person(string&&) { cout << "右值" << endl; } }; //1.值传递的方式 _person make_factory(string person) { return _person(person); } //结果:会造成拷贝操作,结果都为左值 //2.左值引用传递的方式 _person make_factory(string& person) { return _person(person); } //结果:调用函数会报错 //3..右值值引用传递的方式 _person make_factory(string&& person) { return _person(person); } //结果:调用函数会报错 //4..connst引用传递的方式 _person make_factory(string& person) { return _person(person); } //使得传递的参数增加const性,构造函数无法匹配 void test() { string str = "xiaozhang"; //传递左值 make_factory(str); //传递右值 make_factory(move(str)); } int main() { test(); return 0; }
我们希望参数是“原封不动”的性质,所以上面这些方式都不能实现,那我们如何去解决这个问题呢,C++支持模板技术,对于函数模板,可以实现类型的自动推导,加上引用折叠的技术
引用折叠:T&& 多种类型做合在一起的时候,通过编译器的一组规则确定最终的引用
#include <iostream>
using namespace std;
struct _person
{
_person(string&) {
cout << "左值" << endl;
}
_person(string&&) {
cout << "右值" << endl;
}
};
//函数模板
template<class T>
_person make_factory(T&& person) {
return _person(person);
}
void test() {
string str = "xiaozhang";
//传递左值
make_factory(str);
//传递右值
make_factory(move(str));
}
int main()
{
test();
return 0;
}
运行结果发现
左值
左值
结果还是不对,原因是什么呢
右值引用:可以这么理解,右值是即将废弃的对象,右值引用的目的就是为了给这些废弃的对续命,此时,无论左值,右值对象都变成了具名对象,变成了左值对象了,所以才出现这样的结果。
只要把参数转化回去就行了stctic_cast<T&&>(),或者使用forwardforward<T>函数就行了,forward<T>函数底层就是强制转换这种方式
#include <iostream>
using namespace std;
struct _person
{
_person(string&) {
cout << "左值" << endl;
}
_person(string&&) {
cout << "右值" << endl;
}
};
//函数模板
template<class T>
_person make_factory(T&& person) {
return _person(static_cast<T&&>(person));
}
void test() {
string str = "xiaozhang";
//传递左值
make_factory(str);
//传递右值
make_factory(move(str));
}
int main()
{
test();
return 0;
}