为什么std::shared_ptr要存两个指针?

auto sp = std::make_shared<int>();
auto sz = sizeof(sp); // 2个指针的大小

看了下libcxx的实现,是在std::shared_ptr内部存了两个指针,一个指向原始指针,一个指向control block,同时control block又保存一个原始指针,std::shared_ptr保存的原始指针只在std::shared_ptr::get()用到,实际上std::shared_ptr::get()里面也可以从control block里面把真正的原始指针拿出来强转回去吧,类似下面这样:

template<typename T>
class shared_ptr<T> {
    T *ptr_;
    shared_weak_count *cntrl_;
};

template<typename T>
T *std::shared_ptr<T>::get() {
    return (T*)cntrl_->ptr_;
}

为什么不直接全部保存到control block中。

阅读 3.7k
2 个回答

shared_ptr的构造函数里有这样一个重载(aliasing constructor):

template <class Y>  
shared_ptr(const shared_ptr<Y>& r, element_type* ptr) noexcept;

这会让两个不同类型的shared_ptr共享同一个control block。如果只在control block里存一个指针,那这就无法实现了。

并且如果不在control block里存指针,那么用到aliasing constructor的情景在析构的时候会出问题。

所以需要两个指针。

这样设计可以使得不使用虚析构函数也能正确释放对象,甚至shared_ptr<void> ptr 也能正确释放对象,因为control block在构造的时候就捕获了指针的真正类型和delete操作。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题