之前小节介绍了移动构造函数和std::move的作用,本小节将基于此介绍相关的std::forward功能。std::forward的作用是:如果参数不是左值引用那么返回右值引用,如果参数是左值引用,不作修改返回,我们基于move的实例来说明:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
class Str{
public:
char *str;
Str(char value[])
{
cout<<"origin construct function..."<<endl;
str = NULL;
int len = strlen(value);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,value);
}
Str(const Str &s)
{
cout<<"copy construct function..."<<endl;
str = NULL;
int len = strlen(s.str);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,s.str);
}
Str(Str &&s)
{
cout<<"move construct function..."<<endl;
str = s.str;
s.str = NULL;
}
~Str()
{
cout<<"destruct funciton..."<<endl;
if(str != NULL)
{
delete []str;
str = NULL;
}
}
};
template<typename T>
Str* createStr(T t) {
return new Str(t);
}
template<typename T>
Str* createStr1(T t) {
return new Str(std::forward<T>(t));
}
int main()
{
char value[] = "Hello World!";
std::cout << "step 1" << std::endl;
Str s1(value);
Str s2(value);
std::cout << "step 2" << std::endl;
createStr(s1);
std::cout << "step 3" << std::endl;
createStr(std::move(s1));
std::cout << "step 4" << std::endl;
createStr1(std::move(s2));
return 0;
}
输出结果如下:
step 1
origin construct function...
origin construct function...
step 2
copy construct function...
copy construct function...
destruct funciton...
step 3
move construct function...
copy construct function...
destruct funciton...
step 4
move construct function...
move construct function...
destruct funciton...
destruct funciton...
destruct funciton...
可以看到,对于step3,如果不加std::foward,尽管模板函数createStr输入为右值引用,但在进一步传递给构造函数时,由于其为变量,都会被认为是左值,这时需要加上std::forwad来依然保持其为右值引用,从而两次都调用了移动构造函数,提升了效率,这就是std::forward的作用。