C++0x,std::move和std::forward解析
1.std::move
1.1std::move是如何定義的
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
1.2 std::move是如何工作的
1.2.1傳入一個右值
a.如果傳入是一個右值string,比如“hello”,推斷出_Tp類型為string
b.std::remove_reference<_Tp>::type的類型依舊為string
c.move函數的返回類型為string&&
d.move函數的參數類型為string&&
e.static_cast顯式轉換類型為string&&
1.2.2傳入一個左值
a.推斷出_Tp的類型為string&
b.std::remove_reference<_Tp>::type的類型為string
c.move函數的返回類型為string&&
d.move函數的參數類型為string& &&,會折疊為string&
e.static_cast顯式轉換類型為string&&
1.3引用折疊
a.X& &,X& &&和X&& &都折疊為X&
b.X&& && 折疊為X&&
2.std::forward
2.1std::forward是如何定義的
復制代碼
/**
* @brief Forward an lvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }
/**
* @brief Forward an rvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
" substituting _Tp is an lvalue reference type");
return static_cast<_Tp&&>(__t);
}
復制代碼
2.2std::forward是如何工作的
2.2.1_Tp類型是左值引用
a.如果中轉函數的實參是左值string,_Tp的類型為string&,std::remove_reference<_Tp>::type為string
b.forward函數參數__t的類型折疊後為string&
c.string& && (_Tp&&)折疊後依舊為左值引用string&
d.forword函數的返回為string&
2.2.2_Tp類型是右值
a.如果中轉實參是右值sting,_Tp的類型為sting,std::remove_reference<_Tp>::type為string
b.forward函數參數__t的類型為string&&
c.forword函數的返回為string&&
2.3 模版重載
因為存在模版重載機制,所以左值使用第一個版本,而右值選擇第二個版本。
3.STL轉發的例子
復制代碼
// shared_ptr.h
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
{ }
template<typename _Tp, typename _Alloc, typename... _Args>
inline shared_ptr<_Tp>
allocate_shared(const _Alloc& __a, _Args&&... __args)
{
return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
std::forward<_Args>(__args)...);
}
template<typename _Tp, typename... _Args>
inline shared_ptr<_Tp>
make_shared(_Args&&... __args)
{
typedef typename std::remove_const<_Tp>::type _Tp_nc;
return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
std::forward<_Args>(__args)...);
}
復制代碼
復制代碼
//shared_ptr_base.h
#ifdef __GXX_RTTI
protected:
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
std::forward<_Args>(__args)...)
{
// _M_ptr needs to point to the newly constructed object.
// This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
void* __p = _M_refcount._M_get_deleter(typeid(__tag));
_M_ptr = static_cast<_Tp*>(__p);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
}
#else
template<typename _Alloc>
struct _Deleter
{
void operator()(_Tp* __ptr)
{
typedef allocator_traits<_Alloc> _Alloc_traits;
_Alloc_traits::destroy(_M_alloc, __ptr);
_Alloc_traits::deallocate(_M_alloc, __ptr, 1);
}
_Alloc _M_alloc;
};
template<typename _Alloc, typename... _Args>
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: _M_ptr(), _M_refcount()
{
typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
_Deleter<_Alloc2> __del = { _Alloc2(__a) };
typedef allocator_traits<_Alloc2> __traits;
_M_ptr = __traits::allocate(__del._M_alloc, 1);
__try
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2070. allocate_shared should use allocator_traits<A>::construct
__traits::construct(__del._M_alloc, _M_ptr,
std::forward<_Args>(__args)...);
}
__catch(...)
{
__traits::deallocate(__del._M_alloc, _M_ptr, 1);
__throw_exception_again;
}
__shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc);
_M_refcount._M_swap(__count);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
}
#endif
復制代碼
//new_allocator.h
#if __cplusplus >= 201103L
template<typename _Up, typename... _Args>
void
construct(_Up* __p, _Args&&... __args)
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
上面STL例子,還應用了可變參數模版和轉發參數包語法,需要進一步了解。本人水平有限,如果錯誤請指正謝謝。