侵入式智能指针 boost::intrusive_ptr
source link: https://zhiqiang.org/coding/boost-intrusive-ptr.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
侵入式智能指针 boost::intrusive_ptr
如果理解了侵入式容器,侵入式智能指针也很容易理解。传统的智能指针std::shared_ptr
使用了和数据无关的引用计数,这带来两个问题:
- 引用计数要在
shared_ptr
对象间共享,所以它只能位于堆上。这使得每次都需要重新new
一小块内存。这导致性能问题。 - 引用计数的内存区域和数据区域不一致,缓存失效导致性能问题。
- 编写代码不善,将导致同一个数据,绑定到了两个引用计数,从而导致双重删除问题。典型代码如下:
int* x = new int; std::shared_ptr<int> x1 = x; std::shared_ptr<int> x2 = x;
侵入式智能指针试图解决这些问题,方法也特别直接,那就是将引用计数直接塞进数据本身,和数据共存亡。从用户角度,这只需要继承boost::intrusive_ptr_base
基类:
struct T : public boost::intrusive_ptr_base<T> { int age; std::string name; }; T* t = new T(); // 下面这么些很安全,而且速度很快! boost::intrusive_ptr<T> x1 =t; boost::intrusive_ptr<T> x2 =t;
我们看boost::intrusive_ptr_base
的定义,其核心就是增加一个原子操作的引用计数,以及自增和自减引用计数的函数:
template<class T> class boost::intrusive_ptr_base { public: intrusive_ptr_base() : ref_count(0) {} friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* p) { ++p->ref_count; } friend void intrusive_ptr_release(intrusive_ptr_base<T> const* p) { if (--p->ref_count == 0) { boost::checked_delete(static_cast<T const*>(s)); } } boost::intrusive_ptr<T> self() { return boost::intrusive_ptr<T>((T*)this); } private: mutable boost::detail::atomic_count ref_count; };
接下来实际的boost::intrusive_ptr
的定义就很简单了:
template<class T> class boost::intrusive_ptr { public: intrusive_ptr(T* p, bool add_ref = true) : px(p) { if (px != 0 && add_ref) { intrusive_ptr_add_ref(px); } } ~intrusive_ptr() { if (px != 0) { intrusive_ptr_release(px); } } private: T * px; }
由于解决了std::shared_ptr
的三个问题,boost::intrusive_ptr
的效率更高。但它也有缺陷。除了侵入式设计之外,最重要的是boost::intrusive_ptr
无法支持weak_ptr
,从而无法解决环形引用问题。这时因为std::shared_ptr
里的数据对象和计数器分离,可以有不同的生命周期。shared_ptr
的引用计数里有两个计数对象,从而支持weak_ptr
。
另外一个方面,std::shared_ptr
也意识到了其性能问题,内部也提供机制解决这些问题,其核心便是std::make_shared
和std::enable_shared_from_this
。
参考:C++智能指针 3 :内存布局(非侵入式、enable_shared_from_this & 侵入式)
Q. E. D.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK