个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
参考:https://stackoverflow.com/questions/20895648/difference-in-make-shared-and-normal-shared-ptr-in-c
std::make_shared是一个有意思的函数模板,它的使用,用于构造std::shared_ptr对象:
#include <memory>
// 下面两个都用来构建share_ptr对象
std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
std::shared_ptr<Object> p2(new Object("foo"));
但std::make_shared不同与std::shared_ptr的直接构造过程。
std::shared_ptr直接构造时,会涉及调用时传入的new Object(“foo”)对象,然后构造函数内部的new _Ref_count<_Ux>(_Px)存储计数,涉及两次堆内存分配。
template<class _Ty> class shared_ptr : public _Ptr_base<_Ty>
template<class _Ty> class _Ptr_base
element_type * _Ptr{nullptr};
_Ref_count_base * _Rep{nullptr};
_Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ux>(_Px));
template<class _Ty> class _Ref_count public _Ref_count_base
_Ty * _Ptr;
class __declspec(novtable) _Ref_count_base
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
std::make_shared构造时,把Object对象与_Ref_count_base计数放到了一个_Ref_count_obj类中,一次new _Ref_count_obj分配出来,只涉及一次堆内存分配;
接着把分配出的内容指针加上偏移放入到std::shared_ptr的_Ptr, _Rep指针上完成std::shared_ptr构造。
// 在_Ref_count_obj中同时存储object与计数项
class __declspec(novtable) _Ref_count_base
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
template<class _Ty> class _Ref_count_obj public _Ref_count_base
aligned_union_t<1, _Ty> _Storage;
// FUNCTION TEMPLATE make_shared
template<class _Ty, class... _Types>
_NODISCARD inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
{// make a shared_ptr
const auto _Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);
shared_ptr<_Ty> _Ret;
_Ret._Set_ptr_rep_and_enable_shared(_Rx->_Getptr(), _Rx);
return (_Ret);
}
// std::shared_ptr类的直接设值对象与计数的接口
void _Set_ptr_rep(element_type * _Other_ptr, _Ref_count_base * _Other_rep)
{// take new resource
_Ptr = _Other_ptr;
_Rep = _Other_rep;
}
从堆上内存分配的角度来看,std::make_shared的使用,对比直接使用std::shared_ptr构造,可以减少一次堆内存的申请;
同时,因为内存在一起,ref_count与object的释放也是在一起的,不能够单独释放;这个即算是好处—减少了误操作,便于理解;也算是弊端—如果想单独提前把Object转移给别的对象,就做不到了。
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)