std::move(t)负责将t的类型转换为右值引用,这种功能颇有用,能够用在swap中,也能够用来解决完美转发。c++
std::move()的源码以下spa
template<class _Ty> inline _CONST_FUN typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT { // forward _Arg as movable return (static_cast<typename remove_reference<_Ty>::type&&>(_Arg)); }
先说一下实参为左值的状况。code
按理来讲左值是没法匹配右值形参的,可是c++为了move这个基础设施开了两个例外。blog
第一个例外是当形参为右值引用,实参为左值时,编译器推断模板类型参数为实参的左值引用类型。好比rem
template<typename T> void f(T&&); int i; f(i);
这样编译器推断T为int &类型。编译器
可是按以前的规定,咱们并不能直接定义引用的引用,因而有了第二个例外——引用折叠。源码
引用折叠的规则以下:it
& & == & && == && & == &编译
&& && == &&ast
有了这两个例外,move就能够接受任何类型的实参,从而得到一个右值引用。
std::forward()源码以下:
template<class _Ty> inline _CONST_FUN _Ty&& forward( typename remove_reference<_Ty>::type& _Arg) _NOEXCEPT { // forward an lvalue as either an lvalue or an rvalue return (static_cast<_Ty&&>(_Arg)); }
forward()必须经过显式模板实参来调用,并返回该显示模板实参的右值引用。好比std::forward<T>的返回类型为T&&。
forward的使用一般以下:
template<class T> void fwd(T&& t) { foo(std::forward<T>(t)); }
若实参为左值,根据引用折叠,T为左值引用,则执行foo()的实参为左值引用;若实参为右值,则执行foo()的实参为右值引用,符合完美转发。