文章目录
标准库move函数时使用右值引用的模板的一个很好的例子。研究move是如何工作的可以帮助巩固对模板的理解和使用。
move函数只有唯一一个功能:获得一个绑定到左值上的右值引用,以通过右值引用的方式使用该左值。move可以接受任何类型的实参,因此它必然是一个函数模板。它的实现基于C++ 引用折叠和右值引用参数中的两个规则。
定义
标准库这样定义move:
template<typename T>
typename remove_reference<T>::type&& move(T&& t)
{
return static_cast<typename remove_reference<T>::type&&>(t);
}
move的函数参数T&&是一个指向模板类型参数的右值引用,因此通过引用折叠,此参数可以与任何类型的实参匹配,既可以向它传递左值,也可以向它传递右值:
string s1("hi");
string s2 = std::move(string("hi!"));//从一个右值移动数据
s2 = std::move(s1);//将右值引用绑定到左值
std::move如何工作
第一个赋值中,传递给move的实参是一个右值string(“hi!”)。当一个右值引用函数参数传递一个右值时,实参推断出的类型为被引用的类型。因此,在第一个赋值中:
- 推断出T的类型为string
- remove_reference使用string进行实例化
- remove_reference<string>的type是string
- move返回类型为string &&
- move的参数t类型是string &&
因此这个调用实例化为
string && move(string &&t)
在VS上使用速览可以看到实例化模板确实如上
函数体返回static_cast<typename remove_reference::type&&>(t),在该例中即为static_cast<string &&>(t),没有发生类型转换,调用结果就是函数接受的右值引用
第二个赋值传递给move一个左值,可以做出如下推断:
- 推断出T的类型为string &
- remove_reference使用string &进行实例化
- remove_reference<string &>的type是string
- move返回string &&
- move参数t类型为 string& &&,通过引用折叠为string &
因此这个调用实例化为
string && move(string &t)
在该例中t为string &,static_cast<string &&>(t)将其转换为string &&。