Effective Modern C++ 之 引用折叠

前面我们介绍到,当函数模板的形参的型别为万能引用时,当传递给该函数模板的实参是个左值时,则推导出的形参的类型型别为左值引用,当传递给该函数模板的实参是个右值时,则推导出的形参的类型型别为右值引用。还有在实现完美转发时,当传递给调用者的实参是左值时,使用std::forward()被调者的形参的型别为左值引用,当传递给调用者的实参是右值时,使用std::forward()被调者的形参的型别为右值引用。我们先看一个简单的例子:

template<typename T>
void _fun(T&& t) {};

当我们为_fun()传递实参时,函数模板T的推导结果型别中,会把传给传递给该函数是左值还是右值的信息编码到T里面去。因此,当我们传递的实参是个左值,T的型别被推导为T&,当我们传递的实参是个右值,T的型别被推导为T。但是为什么传递的实参是左值时,t的类型型别为左值引用呢?答案:发生了引用折叠。

因为存在右值引用和左值引用,使用引用折叠分四种情况:右值——右值-->右值引用    左值——左值-->左值引用   右值引用——左值引用-->左值引用  左值引用——右值引用-->左值引用  。也就是说任意引用为左值引用,则结果为左值引用,否则结果为右值引用。

std::forward()的实质是应用了引用折叠和强制类型转换。

template<typename T>
T&& forward(std::remove_reference_t<T>& t) {
	return static_cast<T&&>(t);
}

以上是std::forward()的简单实现。我们可以发现不管传递的是左值还是右值,都会进行引用折叠。但是只有传递的是右值时才进行强制类型转换。

引用折叠出现的语境有四种:第一,模板的类型推导。  第二,auto的类型推导(实质就是模板的类型推导)。第三,typedef和别名声明(using)。第四,decltype的使用

发布了78 篇原创文章 · 获赞 11 · 访问量 5070

猜你喜欢

转载自blog.csdn.net/qq_43145594/article/details/104277671