C++智能指针 intrusive_ptr
intrusive_ptr:
intrusive_ptr是一个侵入式的引用计数型指针,它可以用于以下两种情形:
【1】对内存占用的要求非常严格,要求必须与原始指针一样;
【2】现存代码已经有了引用计数机制管理的对象
boost::intrusive_ptr一种“侵入式”的引用计数指针,它实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能,并提供intrusive_ptr_add_ref和intrusive_ptr_release函数接口供boost::intrusive_ptr调用。
下面通过一个具体的例子来说明boost::intrusive_ptr的用法,首先实现一个基类intrusive_ptr_base,定义intrusive_ptr_add_ref和intrusive_ptr_release函数来提供引用计数功能。
/*** intrusive_ptr_base基类,提供intrusive_ptr_add_ref()和intrusive_ptr_release()函数来提供引用计数功能;* 使用boost::intrusive_ptr指针存储的用户类类型必须继承自intrusive_ptr_base基类。*/#include <ostream>#include <boost/checked_delete.hpp>#include <boost/detail/atomic_count.hpp>template<class T>class intrusive_ptr_base {public:/*** 缺省构造函数*/intrusive_ptr_base(): ref_count(0) {std::cout << " Default constructor " << std::endl;}/*** 不允许拷贝构造,只能使用intrusive_ptr来构造另一个intrusive_ptr*/intrusive_ptr_base(intrusive_ptr_base<T> const&): ref_count(0) {std::cout << " Copy constructor..." << std::endl;}/*** 不允许进行赋值操作*/intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs) {std::cout << " Assignment operator..." << std::endl;return *this;}/*** 递增引用计数(放到基类中以便compiler能找到,否则需要放到boost名字空间中)*/friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s) {std::cout << " intrusive_ptr_add_ref..." << std::endl;assert(s->ref_count >= 0);assert(s != 0);++s->ref_count;}/*** 递减引用计数*/friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s) {std::cout << " intrusive_ptr_release..." << std::endl;assert(s->ref_count > 0);assert(s != 0);if (--s->ref_count == 0)boost::checked_delete(static_cast<T const*>(s)); //s的实际类型就是T,intrusive_ptr_base<T>为基类}/*** 类似于shared_from_this()函数*/boost::intrusive_ptr<T> self() {return boost::intrusive_ptr<T>((T*)this);}boost::intrusive_ptr<const T> self() const {return boost::intrusive_ptr<const T>((T const*)this);}int refcount() const {return ref_count;}private:///should be modifiable even from const intrusive_ptr objectsmutable boost::detail::atomic_count ref_count;}; 用户类类型需要继承intrusive_ptr_base基类,以便具有引用计数功能。#include <iostream>#include <string>#include <boost/intrusive_ptr.hpp>#include "intrusive_ptr_base.hpp"/*** 用户类类型继承自intrusive_ptr_base,该实现方式类似于boost::enable_shared_from_this<Y>*/class Connection : public intrusive_ptr_base< Connection > {public:/*** 构造函数,调用intrusive_ptr_base< Connection >的缺省构造函数来初始化对象的基类部分*/Connection(int id, std::string tag):connection_id( id ), connection_tag( tag ) {}/*** 拷贝构造函数,只复制自身数据,不能复制引用计数部分*/Connection(const Connection& rhs):connection_id( rhs.connection_id ), connection_tag( rhs.connection_tag) {}/*** 赋值操作,同样不能复制引用计数部分*/const Connection operator=( const Connection& rhs) {if (this != &rhs) {connection_id = rhs.connection_id;connection_tag = rhs.connection_tag;}return *this;}private:int connection_id;std::string connection_tag;};int main() {std::cout << "Create an intrusive ptr" << std::endl;boost::intrusive_ptr< Connection > con0 (new Connection(4, "sss") ); //调用intrusive_ptr_add_ref()递增引用计数std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl;boost::intrusive_ptr< Connection > con1 (con0); //调用intrusive_ptr_add_ref()std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl;boost::intrusive_ptr< Connection > con2 = con0; //调用intrusive_ptr_add_ref()std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl;std::cout << "Destroy an intrusive ptr" << std::endl;return 0;} 程序运行输出:Create an intrusive ptrDefault constructor intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 1intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 2intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 3
Destroy an intrusive ptrintrusive_ptr_release...intrusive_ptr_release...intrusive_ptr_release...
对比boost::shared_ptr
使用boost::shared_ptr用户类本省不需要具有引用计数功能,而是由boost::shared_ptr来提供;使用boost::shared_ptr的一大陷阱就是用一个raw pointer多次创建boost::shared_ptr,这将导致该raw pointer被多次销毁当boost::shared_ptr析构时。即不能如下使用:
那么为什么通常鼓励大家使用shared_ptr,而不是intrusive_ptr呢, 在于shared_ptr不是侵入性的,可以指向任意类型的对象; 而intrusive_ptr所要指向的对象,需要继承intrusive_ptr_base,即使不需要,引用计数成员也会被创建。
智能指针intrusive_ptr一般情况下不要使用,除非被指类的某个成员函数需要返回this指针。因为intrusive_ptr需要自己实现引用计数,所以实现起来比较复杂。还要实现intrusive_ptr_add_ref和intrusive_ptr_release两个函数。参考《Beyond the C++ Standard Library: An Introduction to Boost》和网络文章http://www.cnblogs.com/edwardlost/archive/2011/02/17/1957019.html两篇资料,比较之后觉得网络文章中的示例代码更能够完善准确的表达出来intrusive_ptr的使用方法和注意事项。具体情况请看注释。[cpp] view plaincopyprint?// instrusive_ptr.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <boost/intrusive_ptr.hpp> // 主要介绍的对象——智能指针intrusive_ptr头文件
#include <boost/detail/atomic_count.hpp> // Boost库提供的线程安全的原子计数器
#include <boost/checked_delete.hpp> // 对指针进行静态检查的函数
#include <iostream>
#include <cassert> // 使用intrusive_ptr智能指针需要指向的类继承自intrusive_ptr_base,
// 以便于自动实现引用计数。
template<class T>
class intrusive_ptr_base
{
private: // 引用计数——初始化为0 // mutable:为了突破引用计数的获取函数intrusive_ptr_add_ref,intrusive_ptr_release // 类型atomic_count保证了线程安全。 mutable boost::detail::atomic_count ref_count;
public: // 缺省构造函数 intrusive_ptr_base() : ref_count(0) { // 下面代码只是为了演示 std::cout << " Default constructor " << std::endl; } // 复制构造函数,啥都不实现,也就是不允许此操作 // 实现此函数无功能的目的是为了子类进行复制构造函数时不复制引用计数ref_count intrusive_ptr_base(intrusive_ptr_base<T> const& rhs) : ref_count(0) { // 下面代码只是为了演示 std::cout << " Copy constructor... " << std::endl; } // 赋值操作,啥都不实现,也就是不允许此操作 // 实现此函数无功能的目的是为了子类进行复制构造函数时不复制引用计数ref_count intrusive_ptr_base& operator=(intrusive_ptr_base<T> const& rhs) { // 下面代码只是为了演示 std::cout << " Assignment operator... " << std::endl; return *this; } // 递增引用计数 // 用友元函数的方式来实现,避免了函数指针类型的转换 // 例如: // template<typename T> void intrusive_ptr_add_ref(T* t) // { // T->add_ref(); // 此处需要定义T的原型 // } friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s) { // 下面代码只是为了演示 std::cout << " intrusive_ptr_add_ref... " << std::endl; // 判断合法性并自增 assert(s != 0); assert(s->ref_count >= 0); ++s->ref_count; } // 递增引用计数 // 用友元函数的方式来实现,避免了函数指针类型的转换 // 例如: // template<typename T> void intrusive_ptr_release(T* t) // { // T->release(); // 此处需要定义T的原型 // } friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s) { // 下面代码只是为了演示 std::cout << " intrusive_ptr_release... " << std::endl; // 判断合法性并自减 assert(s != 0); assert(s->ref_count >= 0); if (--s->ref_count == 0) { // 进行静态类型检查,防止出错 boost::checked_delete(static_cast<T const*>(s)); } } // this指针 可改变操作 boost::intrusive_ptr<T> self() { return boost::intrusive_ptr<T>((T*)this); } // this指针 不可改变操作 boost::intrusive_ptr<T> self() const { return boost::intrusive_ptr<const T>((T const*)this); } // 获取引用计数 int refcount() const { return ref_count; }
}; // 子类,继承自intrusive_ptr_base
// 自动获得引用计数功能
class Connection : public intrusive_ptr_base<Connection>
{
private: // 数据定义 int connection_id; std::string connection_tag;
public: // 构造函数 Connection(int id, std::string tag) : connection_id(id), connection_tag(tag) {} // 复制构造函数,因为父类实现了无操作函数,导致引用计数不被复制 Connection(const Connection& rhs) : connection_id(rhs.connection_id), connection_tag(rhs.connection_tag) {} // 赋值操作函数,因为父类实现了无操作函数,导致引用计数不被复制 const Connection operator=(const Connection& rhs) { if (this != &rhs) { connection_id = rhs.connection_id; connection_tag = rhs.connection_tag; } return *this; }
}; int _tmain(int argc, _TCHAR* argv[])
{ // 添加这个大括号是为了能够在getchar()函数执行之前就获取到Connect类三个 // 智能指针销毁的操作输出字符。 { std::cout << "Create an intrusive ptr" << std::endl; boost::intrusive_ptr<Connection> con0(new Connection(4, "sss")); std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl; // 复制构造函数的调用 boost::intrusive_ptr<Connection> con1(con0); std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl; // 赋值函数的调用 boost::intrusive_ptr<Connection> con2 = con0; std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl; std::cout << "Destroy an intrusive ptr" << std::endl; } getchar(); return 0;
} // instrusive_ptr.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <boost/intrusive_ptr.hpp> // 主要介绍的对象——智能指针intrusive_ptr头文件
#include <boost/detail/atomic_count.hpp> // Boost库提供的线程安全的原子计数器
#include <boost/checked_delete.hpp> // 对指针进行静态检查的函数
#include <iostream>
#include <cassert>// 使用intrusive_ptr智能指针需要指向的类继承自intrusive_ptr_base,
// 以便于自动实现引用计数。
template<class T>
class intrusive_ptr_base
{
private:// 引用计数——初始化为0// mutable:为了突破引用计数的获取函数intrusive_ptr_add_ref,intrusive_ptr_release// 类型atomic_count保证了线程安全。mutable boost::detail::atomic_count ref_count;
public:// 缺省构造函数intrusive_ptr_base() : ref_count(0){// 下面代码只是为了演示std::cout << " Default constructor " << std::endl;}// 复制构造函数,啥都不实现,也就是不允许此操作// 实现此函数无功能的目的是为了子类进行复制构造函数时不复制引用计数ref_countintrusive_ptr_base(intrusive_ptr_base<T> const& rhs) : ref_count(0){// 下面代码只是为了演示std::cout << " Copy constructor... " << std::endl;}// 赋值操作,啥都不实现,也就是不允许此操作// 实现此函数无功能的目的是为了子类进行复制构造函数时不复制引用计数ref_countintrusive_ptr_base& operator=(intrusive_ptr_base<T> const& rhs){// 下面代码只是为了演示std::cout << " Assignment operator... " << std::endl;return *this;}// 递增引用计数// 用友元函数的方式来实现,避免了函数指针类型的转换// 例如:// template<typename T> void intrusive_ptr_add_ref(T* t)// {// T->add_ref(); // 此处需要定义T的原型// }friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s){// 下面代码只是为了演示std::cout << " intrusive_ptr_add_ref... " << std::endl;// 判断合法性并自增assert(s != 0);assert(s->ref_count >= 0);++s->ref_count;}// 递增引用计数// 用友元函数的方式来实现,避免了函数指针类型的转换// 例如:// template<typename T> void intrusive_ptr_release(T* t)// {// T->release(); // 此处需要定义T的原型// }friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s){// 下面代码只是为了演示std::cout << " intrusive_ptr_release... " << std::endl;// 判断合法性并自减assert(s != 0);assert(s->ref_count >= 0);if (--s->ref_count == 0){// 进行静态类型检查,防止出错boost::checked_delete(static_cast<T const*>(s));}}// this指针 可改变操作boost::intrusive_ptr<T> self(){return boost::intrusive_ptr<T>((T*)this);}// this指针 不可改变操作boost::intrusive_ptr<T> self() const{return boost::intrusive_ptr<const T>((T const*)this);}// 获取引用计数int refcount() const{return ref_count;}
};// 子类,继承自intrusive_ptr_base
// 自动获得引用计数功能
class Connection : public intrusive_ptr_base<Connection>
{
private: // 数据定义int connection_id;std::string connection_tag;
public:// 构造函数Connection(int id, std::string tag): connection_id(id), connection_tag(tag) {}// 复制构造函数,因为父类实现了无操作函数,导致引用计数不被复制Connection(const Connection& rhs): connection_id(rhs.connection_id),connection_tag(rhs.connection_tag) {}// 赋值操作函数,因为父类实现了无操作函数,导致引用计数不被复制const Connection operator=(const Connection& rhs){if (this != &rhs){connection_id = rhs.connection_id;connection_tag = rhs.connection_tag;}return *this;}
};int _tmain(int argc, _TCHAR* argv[])
{// 添加这个大括号是为了能够在getchar()函数执行之前就获取到Connect类三个// 智能指针销毁的操作输出字符。{std::cout << "Create an intrusive ptr" << std::endl;boost::intrusive_ptr<Connection> con0(new Connection(4, "sss"));std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl;// 复制构造函数的调用boost::intrusive_ptr<Connection> con1(con0);std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl;// 赋值函数的调用boost::intrusive_ptr<Connection> con2 = con0;std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl;std::cout << "Destroy an intrusive ptr" << std::endl;}getchar();return 0;
}上面的代码实现了线程安全、引用计数和类型检测,是成熟的代码,可以复用。因为使用intrusive_ptr需要实现对intrusive_ptr_base的继承,要是原来有引用计数的程序很适用,否则比较麻烦。所以需要自己取舍。
C++智能指针 intrusive_ptr相关推荐
- 代码注释法学习智能指针intrusive_ptr
智能指针intrusive_ptr一般情况下不要使用,除非被指类的某个成员函数需要返回this指针. 因为intrusive_ptr需要自己实现引用计数,所以实现起来比较复杂.还要实现intrusiv ...
- Boost库基础-智能指针(intrusive_ptr)
intrusive_ptr intrusive_ptr是一种引用计数型智能指针,与之前介绍的scoped_ptr.shared_ptr不同,需要额外增加一些的代码才能使用. 如果现存代码已经有了引用计 ...
- 【Boost】boost库中智能指针——intrusive_ptr
boost::intrusive_ptr一种"侵入式"的引用计数指针,它实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能,并提供intrusive_ptr_add ...
- boost智能指针之shared_ptr,scoped_ptr,intrusive_ptr,weak_ptr源码简析
boost库实现了各种智能指针,基本上都纳入了c++11标准中,boost库的smart_ptr目录下就是各种指针的实现了: 1.shared_ptr template<class T> ...
- C++ boost库智能指针(四):intrusive_ptr
intrusive_ptr这个智能指针不怎么好用,虽然它和shared_ptr也是基于引用计数的,但需要自己来实现引用计数的增加与减少.需要在我们管理的指针对象中添加一个计数的成员,例如下面的类Tes ...
- C++智指针之——boost::intrusive_ptr,一种与shared_ptr、unique_ptr截然不同的智能指针
智能指针boost::shared_ptr/std::shared_ptr使用了和数据无关的引用计数,在使用shared_ptr之前,必须要搞清楚资源的所有权和资源的使用权这两个问题(详见<C+ ...
- 智能指针和内存管理小结
·概述: 主要是两个库:smart_ptr库和pool库. smart_ptr库主要解决的问题是指针的内存泄漏和垃圾回收问题:pool则是解决内存分配问题. 感觉还是smart_ptr库比较好用一些, ...
- C++ 智能指针详解
智能指针内容很多,重点是基本用法. #include <boost/shared_ptr.hpp> class CBase: public boost::enable_shared_fro ...
- 【Boost】boost库中智能指针概述
这篇文章主要介绍 boost中的智能指针的使用. 内存管理是一个比较繁琐的问题,C++中有两个实现方案: 垃圾回收机制和智能指针.垃圾回收机制因为性能等原因不被C++的大佬们推崇, 而智能指针被认为是 ...
最新文章
- python 排序算法 简书_Python---简析八大排序算法
- android相机保存文件为空,相机不保存到指定的文件位置android
- Android Studio Library 模块中 Native 代码进行 debug 的一些坑
- BZOJ3527: [Zjoi2014]力
- cx oracle 配置,cx_Oracle的配置啊。。终于搞出来了
- 【SpringMVC 笔记】结果跳转、数据处理、乱码问题
- js刷新页面有哪几种方法
- golang zip 解压、压缩文件
- notesDocument类的HTTP URL属性 和note URL属性的区别
- CRT 字体颜色设置不生效
- javac编译带有package的java文件
- 每日一面 - mysql中,我存十亿个手机号码,考虑存储空间和查询效率,怎么设计?
- 指南-Luat二次开发教程指南-功能开发教程-功耗管理
- html5手机触屏效果,html5手机触屏touch事件的详细介绍
- VCC AVCC VDD AVDD区别(转载)
- 2020西瓜直播弹幕协议版弹幕提取思路与实现py
- sonar问题:Font declarations should contain at least one generic font family
- 权力的游戏击杀和家族知识图谱(python+neo4j)
- ora-00942表或视图不存在,解决办法
- 为什么中国的程序员总被称为码农