C++:shared

tech2026-03-07  1

C++11标准库中的shared_ptr两种方式

直接调用构造函数make_shared

直接调用构造函数

#include <iostream> #include <memory> using namespace std; class B{ public: CTest ct; char b; ~B(){ cout<<"~B executed"<<endl; } }; class C : public B{ public: ~C(){ cout<<"~C executed"<<endl; } }; int main() { B *bb = new C; shared_ptr<B> p(new C); shared_ptr<B> p2(bb); return 0; }

输出

~C executed //p ~B executed //p ~B executed //p2

为什么p可以输出正确调用父类析构函数呢?看源码

template<typename _Tp>//_Tp对应指定的 B 类型 class shared_ptr : public __shared_ptr<_Tp> //继承自__shared_ptr { ... //这里_Yp是传入指针的类型,也就是 C* template<typename _Yp, typename = _Constructible<_Yp*>> explicit shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { } //显示调用了父类的构造函数。 ... }; //__shared_ptr类 template<typename _Tp, _Lock_policy _Lp> //_Tp -> B class __shared_ptr : public __shared_ptr_access<_Tp, _Lp> { // 获取_Tp最本质的类型,去除[], 这里对应类型就是 B using element_type = typename remove_extent<_Tp>::type; ... template<typename _Yp, typename = _SafeConv<_Yp>> // _Yp -> C explicit __shared_ptr(_Yp* __p) : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()) //又将__p传给了引用计数对象 { static_assert( !is_void<_Yp>::value, "incomplete type" ); static_assert( sizeof(_Yp) > 0, "incomplete type" ); _M_enable_shared_from_this_with(__p); } ... //两个成员变量 element_type* _M_ptr; // 这里保存了B* 类型的指针 __shared_count<_Lp> _M_refcount; // 引用计数对象 }; // __shared_count 类,真正掌握__p的生杀大权 template<_Lock_policy _Lp> class __shared_count { public: constexpr __shared_count() noexcept : _M_pi(0) { } template<typename _Ptr> explicit __shared_count(_Ptr __p) : _M_pi(0) //2. 再调用这个 { __try { _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); //用__p构建了_M_pi对象 } __catch(...) { delete __p; __throw_exception_again; } } template<typename _Ptr> __shared_count(_Ptr __p, /* is_array = */ false_type) //1.先调用这个 : __shared_count(__p) { } ... //成员变量 _Sp_counted_base<_Lp>* _M_pi; }; // _Sp_counted_ptr 类 template<typename _Ptr, _Lock_policy _Lp> class _Sp_counted_ptr final : public _Sp_counted_base<_Lp> { explicit _Sp_counted_ptr(_Ptr __p) noexcept : _M_ptr(__p) { } virtual void _M_dispose() noexcept { delete _M_ptr; } ... private: _Ptr _M_ptr; //看到这里,就明了了, 这是存储的C指针,所以在删除时 };

看到这里,就比较明了, _Sp_counted_ptr存储的是C指针,所以在删除时,也是直接从子类调用析构函数的。

虽然在__shared_ptr中也保存了B的指针,目前猜测它是通过弱引用指向_Sp_counted_ptr中的C指针指向的实例的,并不会析构这个指针。(后续继续阅读源码研究一下。)

make_shared

…未完待续

最新回复(0)