boost的内存管理

smart_ptr

  • raii ( Resource Acquisition Is Initialization )
  • 智能指针系列的都统称为smart_ptr,包括c++98标准的auto_ptr
  • 智能指针是一个类,通过重载->和*完成类似原始指针的操作。不过因为是类,所以可以做比如内存管理、线程安全之类的工作
  • 智能指针均是自动管理内存,不需要显示调用delete

scoped_ptr

  • 与auto_ptr最大的不同,是私有化构造和拷贝构造,使操作权不能转让,所以有强作用域属性,而且指针类自己负责释放
  • 与c++11标准的unique_ptr相比:unique_ptr有更多功能,可以像原始指针一样进行比较、像shared_ptr一样定制删除器,也可以安全地放入标准容器。但是少即是多,scope_ptr专注于强调作用域属性。

scoped_array

  • 与scoped_ptr类似,只不过封装的是new[]分配数组。
  • 不是指针,也就没有实现*和->的重载,而是直接[]下标访问
  • 通常不建议使用scoped_array,它的出现通常往往意味着你的代码中存在着隐患

shared_ptr(重点)

  • boost.smart_ptr中最有价值、最重要的组成部分,也最经常用
  • unique()在shared_ptr是指针中唯一所有者时返回true
  • user_count()返回当前指针的引用计数
  • 提供operator<、==比较操作 ,使shared_ptr可以被用于set/map标准容器
  • 编写多态指针时,不能使用诸如static_cast< T* >(p.get())的形式,这将导致转型后的指针无法再被shared_ptr正确管理。为了支持这样的用法,shared_ptr提供内置的转型函数static_pointer_cast< T >()、const_pointer_cast< T >()和dynamic_pointer_cast< T >()
  • 支持operator< < 操作打印指针值,便与调试
  • 有工厂函数
template< class T, calss... Args >
shared_ptr< T> make_shared(Args && ... args);
  • 使用代码案例:
shared_ptr< string > sps(new string("smart"));
assert(sps->size() == 5);
shared_ptr< string> sp = make_shared< string > ("make_shared");
shared_ptr< vector< int >> spv = make_shared< vector< int >> (10,2);
assert(spv->size() == 10);
  • 应用于标准容器代码案例:
#include < boost/make_shared.hpp>
int main()
{
    typedef vector< shared_ptr< int>> vs;
    vs v(10);
    int i=0;
    for (vs::iterator pos = v.begin(); pos != v.end(); ++pos)
    {
        (*pos) = make_shared< int>(++i);
        cout << *(*pos) << ",";
    }
    cout << endl;
    shared_ptr < int > p = v[9];
    *p = 100;
    cout << *v[9] << endl;
}

shared_array

  • 通常用shared_ptr< std::vector>或者std::vector< shared_ptr>代替

weak_ptr(重点)

  • 未重载*和->,最大的作用是协助shared_ptr,观测资源使用情况
  • 代码示例:
int testWeakPtr()
{
    boost::shared_ptr<int> sp(new int(10));
    assert(sp.use_count() == 1);

    boost::weak_ptr<int> wp(sp);
    assert(wp.use_count() == 1);

    if (!wp.expired())
    {
        boost::shared_ptr<int> sp2 = wp.lock();
        *sp2 = 100;
        assert(sp2.use_count() == 2);
        assert(wp.use_count() == 2);
    }

    assert(wp.use_count() == 1);
    sp.reset();
    assert(wp.expired());
    assert(!wp.lock());

    return 0;
}
  • 作用是打破循环引用,代码示例:
// 循环引用的情形
class node
{
public:
    boost::shared_ptr<node> next;
    ~node()
    {
        cout << "delete node" << endl;
    }
};

int testWeakPtrRecycleWrong()
{
    auto n1 = boost::make_shared<node>();
    auto n2 = boost::make_shared<node>();

    n1->next = n2;
    n2->next = n1;

    assert(n1.use_count() == 2);
    assert(n2.use_count() == 2);

    return 0; // 循环引用,析构异常,程序退出时仍未析构
}

// 避免循环引用的情形,主要就是node里的shared_ptr换成weak_ptr
class node1
{
public:
    boost::weak_ptr<node1> next;
    ~node1()
    {
        cout << "delete node1" << endl;
    }
};

int testWeakPtrRecycleRight()
{
    auto n1 = boost::make_shared<node1>();
    auto n2 = boost::make_shared<node1>();

    n1->next = n2;
    n2->next = n1;

    assert(n1.use_count() == 1);
    assert(n2.use_count() == 1);

    if (!n1->next.expired())
    {
        // 调用lock()获得强引用,计数加1
        auto n3 = n1->next.lock();
        assert(n2.use_count() == 2);
    }
    assert(n2.use_count() == 1);
    return 0;
}

intrusive_ptr(略)

pool(pool后缀的都是重点)

  • pool管理内存,只能针对基础类型POD(Plain Old Data),因为不调用对象的构造函数。除非特殊情况,不需要自己释放
  • 调用示例代码:
int testPool()
{
    pool<> pl(sizeof(int));
    int *p = static_cast<int*>(pl.malloc()); // void*->int*
    assert(pl.is_from(p));

    pl.free(p);
    for (int i = 0; i < 100;i++)
    {
        pl.ordered_malloc(10);
    }
    return 0;
}

object_pool

  • pool的子类,实现对类实例(对象)的内存池,会调用析构函数正确释放资源
  • 示例代码:
struct demo_class
{
public:
    int a, b, c;
    demo_class(int x = 1, int y = 2, int z = 3) : a(x), b(y), c(z) {}
    ~demo_class()
    {
        cout << "destruct" << endl;
    }
};

int testObjPool()
{
    object_pool<demo_class> pl;
    demo_class *p = pl.malloc();
    assert(pl.is_from(p));

    // malloc 创建时内存并未初始化
    assert(p->a!= 1 || p->b != 2 || p->c != 3);

    p = pl.construct();

    // boost自带的construct只能支持3个及以内的参数调用
    p = pl.construct(7, 8, 9);
    assert(p->a == 7);

    object_pool<string> pls;
    for (int i = 0; i < 10; i++)
    {
        string *ps = pls.construct("hello object_pool");
        cout << *ps << endl;
    }
    return 0;
}

析构会调用三次,malloc和两次construct均需要调用析构。是object_pool判断出了作用域自动调整的。

singleton_pool

  • 基础类型静态单件(包括基础指针类型),提供线程安全
  • 示例代码
struct pool_tag{
    int tag;
};
typedef singleton_pool<pool_tag, sizeof(pool_tag*)> spl;
int testSingletonPool()
{
    pool_tag **p = (pool_tag **)spl::malloc();
    assert(spl::is_from(p));

    pool_tag ptag;
    ptag.tag = 3;
    *p = &ptag;

    cout << "testSingletonPool : " << (*p)->tag << endl;
    spl::release_memory();
    return 0;
}

pool_alloc

  • 提供对标准容器类型的内存分配器,当分配失败时可以抛异常。但是除非特别需求,应该使用stl自带的。如果要用pool_alloc需经过仔细测试,保证与容器可以正常工作。
时间: 2024-10-09 22:15:44

boost的内存管理的相关文章

(六)boost库之内存管理shared_ptr

(六)boost库之内存管理shared_ptr 1.shared_ptr的基本用法 boost::shared_ptr<int> sp(new int(10)); //一个指向整数的shared_ptr assert(sp.unique()); //现在shared_ptr是指针的唯一持有者 boost::shared_ptr<int> sp2 = sp; //第二个shared_ptr,拷贝构造函数 assert(sp == sp2 && sp.use_coun

Object-C内存管理的理解总结

今天看到了OC的内存管理这块,觉得很亲切. 自己的习惯是尽量自己掌控程序的空间和时间,有点强迫症的感觉.用C和C++做项目的时候,时时刻刻都在操心这new和delete的配对使用和计数,学习stl和boost的时候看到了智能指针等时候,依然不是很爱使用,还是愿意坚持自己控制new和delete:后来用C#后,一直特别注意Dispose相关的动作,尽早释放对象占有的内存空间,避免无谓的占用一直到程序退出才释放. OC中系统对每个实例对象地址都记录一个引用次数(当然有特例,见另外一篇随笔),这就是引

C++内存管理变革(6):通用型垃圾回收器 - ScopeAlloc

本文已经迁移到:http://cpp.winxgui.com/cn:a-general-gc-allocator-scopealloc C++内存管理变革(6):通用型垃圾回收器 - ScopeAlloc 许式伟2008-1-22 引言 在前文,我们引入了GC Allocator(具备垃圾回收能力的Allocator),并提供了一个实作:AutoFreeAlloc(具体内容參见<C++内存管理变革(2):最袖珍的垃圾回收器 - AutoFreeAlloc>). 可是,如前所述,AutoFree

C++内存管理学习笔记(5)

/****************************************************************/ /*            学习是合作和分享式的! /* Author:Atlas                    Email:[email protected] /*  转载请注明本文出处: *   http://blog.csdn.net/wdzxl198/article/details/9112123 /************************

c++内存管理学习纲要

本系列文章,主要是学习c++内存管理这一块的学习笔记. 时间:6.7-21 之下以技术内幕的开头语,带入到学习C++内存管理的技术中吧: 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,因此要想成为C++高手,内存管理一关是必须要过的! 笔记汇总: 1.C++内存管理学习笔记(1) 2.C++内存管理学习笔记(2) 3.C++内存管理学习笔记(3) 4.C++内存管理学习笔记(4) 5.C++内存管理学习笔记(5) 6.C++内存管理学习笔记(6) 7.C++内存管理学习笔记(7

C++内存管理学习笔记(4)

/****************************************************************/ /*            学习是合作和分享式的! /* Author:Atlas                    Email:[email protected] /*  转载请注明本文出处: *   http://blog.csdn.net/wdzxl198/article/details/9094793 /************************

【cocos2d-x 3.x 学习笔记】对象内存管理

内存管理 内存管理一直是一个不易处理的问题,开发者必须考虑分配回收的方式和时机,针对堆和栈做不同的优化处理,等等.内存管理的核心是动态分配的对象必须保证在使用完毕后有效地释放内存,即管理对象的生命周期.由于C++是一个较为底层的语言,其设计上不包含任何智能管理内存的机制.一个对象在使用完毕后必须被回收,然而在复杂的程序中,对象所有权在不同程序片段间传递或共享,使得确定回收的时机十分困难,因此内存管理成为了程序员十分头疼的问题. 另一方面,过于零散的对象分配回收可能导致堆中的内存碎片化,降低内存的

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Block内存管理实例分析

在ios开发中,相信说道block大家都不陌生,内存管理问题也是开发者最头疼的问题,网上很多讲block的博客,但大都是理论性多点,今天结合一些实例来讲解下. 存储域 首先和大家聊聊block的存储域,根据block在内存中的位置,block被分为三种类型: NSGlobalBlock NSStackBlock NSMallocBlock 从字面意思上大家也可以看出来 NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中. NSStackBlock是位于