概述
std::forward
是C++11中引入的一个函数模板,用于实现完美转发。它的作用是根据传入的参数,决定将参数以左值引用还是右值引用的方式进行转发。
传统上,当一个左值传递给一个函数时,参数会以左值引用的方式进行传递;当一个右值传递给一个函数时,参数会以右值引用的方式进行传递。完美转发是为了解决传递参数时的临时对象(右值)被强制转换为左值的问题。
std::forward
实现完美转发主要用于以下场景:提高模板函数参数传递过程的转发效率。
一、std::forward、万能引用与完美转发
1、万能引用
对于形如
T&&
的变量或者参数,如果T
可以进行推导,那么T&&
称之为万能引用。换句话说,对于形如T&&
的类型来说,其既可以绑定左值,又可以绑定右值,而这个的前提是T
需要进行推导。最常见的万能引用方式如以下两种:
函数模板:
template<typename T>
void f(T&& param); // 存在类型推导,param是一个万能引用
auto类型推导:
auto&& var = var1; // 存在类型推导,var是一个万能引用
注意:只有当发生自动类型推断时(例如:函数模板的类型自动推导),
T &&
才是万能引用。下面一个示例中的&&
并不是一个万能引用,例如:
template<typename T>
void f( T&& param); // 这里T的类型需要推导,所以&&是一个 universal references
template<typename T>
class Test {
Test(Test&& rhs); // Test是一个特定的类型,不需要类型推导,所以&&表示右值引用
};
2、类型推导
万能引用进行类型推导时需要推导出
T&&
中的T
的真实类型:若传入的参数是一个左值,则T
会被推导为左值引用;而如果传入的参数是一个右值,则T
会被推导为原生类型(非引用类型)。
对于万能引用来说,条件之一就是类型推导,但是类型推导是万能引用的必要非充分条件,也就是说参数必须被声明为
T&&
形式不一定是万能引用。示例如下:
template<typename T>
void func(std::vector<T>&& t); // t是右值引用
调用
func
时会执行类型推导,但是参数t
的类型声明的形式并非T &&
而是std::vector &&
。 之前强调过,万能引用必须是T &&
才行,因此,t
是一个右值引用,如果尝试将左值传入,编译器将会报错:
std::vector<int> v;
fun(v); // 编译错误,不能将左值绑定到右值
形如
const T&&
的方式也不是万能引用:
template<typename T>
void f(const T&am