一、std::move的定义
下面定义截取自gcc源码:
/**
* @brief Convert a value to an rvalue.
* @param __t A thing of arbitrary type.
* @return The parameter cast to an rvalue-reference to allow moving it.
*/
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
函数的注释表明以下几点:
- 此函数用于将一个值转化为一个右值(注意这里没有说是左值还是右值)
__t
是任意类型的参数- 此函数最终会将
__t
转化为一个右值引用类型
二、std::remove_reference的定义
std::remove_reference
也是个函数模板,从名称上就比较好理解,即为移除引用。所以我们只想知道,它是如何移除引用的。
我们来看下std::remove_reference
的定义:
/// remove_reference
template<typename _Tp>
struct remove_reference
{ typedef _Tp type; };
template<typename _Tp>
struct remove_reference<_Tp&>
{ typedef _Tp type; };
template<typename _Tp>
struct remove_reference<_Tp&&>
{ typedef _Tp type; };
从上面的定义我们可以看到无论传入的是值类型(_Tp
),左值引用类型(_Tp&
)还是右值引用类型(_Tp&&
),最终得到的remove_reference<_Tp>::type
都是_Tp
类型,具体参考https://compiler-explorer.com/z/E86M68r3d。
三、综合分析
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::move
的参数被定义为万能引用的形式_Tp&& __t
,这样std::move
就可以接受所有的参数类型,而返回值始终是右值引用的类型。下面我们逐个进行解释,可以参考Item 1: 理解模板类型推导:
这里假设std::move
的调用形式为
auto expire = std::move(expr);
- 如果
expr
为左值的话,会导致_Tp
被推导为左值引用,假设类型为int
,那么type(_Tp)==int&
,根据引用折叠原理type(__t)==int&
- 如果
expr
为右值(将亡值、纯右值),_Tp
的推导会忽略引用部分type(_Tp)==int
, 那么type(__t)=int&
无论type(_Tp)==int&
还是type(_Tp)==int
,std::remove_reference<_Tp>::type&&
的返回类型都会是int&&