`

从引用计数,auto release pool 到 shared ptr

阅读更多

    想起这个话题,是因为最近在研究cocos2d-x,其内存管理机制使用c++模拟了Obj-C的auto release pool机制。先从头说起,这是一种基于引用计数的技术。

我最早接触引用计数,是学习研究irrlicht引擎,当时的感觉是,必须弄清楚每个返回对象的函数,是否grab了对象,虽然irrlicht引擎自己是按照命名规则给予用户提示的,但是别人写的方法可就苦恼了。


 纯粹引用计数的主要问题是,必须很小心的增加和减少计数。主要的内存泄露问题都来自于漏了release。  特别是有一种情况:某某类负责产生了一个对象,但是需要使用者去释放,由于使用者并不需要在他的生命周期内保留这个对象,很可能忘了去release这个对象。怎么办呢?于是有了所谓的“自动释放池”。这个技术是Obj-C所有的,cocos2d-x使用c++模拟了。简单的思想是,负责产生对象的类,在产生对象后把这个对象加入到一个数组中(也就是所谓的auto release pool),在这一帧结束的时候(或者该pool被pop的时候),auto release pool会对其中所有的对象执行一次release,即引用减1。如果某对象没有被使用者retain (引用加1),引用就会被减为0,因此被释放掉。在cocos2d-x中(其实Obj-C也是差不多),会在每次游戏循环时自动pop一次auto release pool,将所有没人管的对象释放掉。默认情况下,系统中只有一个auto release pool,但是如果用户想提前释放某些对象,可以自己push上新的pool,然后在合适的时机pop他。这个和Obj-C的用法也是很像的。那么,从这个过程看,auto release pool解决了什么问题呢? 其实他的作用就是免除了对象指针在离开作用域时,对对象减少引用计数的工作。区别在于,他不是在离开作用域时立即release,而是在一帧结束时统一release。


好了,有了auto release pool,事情简单了很多:

1)如果你retain或new了对象,你就负责release他。

2)如果你new了对象给别人用,你自己不知道别人啥时候用完。你就把他放到auto release pool中(obj->autoRelease(); ),如果别人只是临时用一下他,auto release pool会释放对象。如果别人要较长期的使用它,他需要按第一条规则做,retain对象并在不需要对象时release。


似乎这样很不错了,但再仔细想想,我们还是要retain / release对象,我们还是不能忘记release,这和new了对象不能忘记delete没什么区别。使用引用计数的好处是可以很容易的共享对象所有权(当然要防止交叉引用的问题),并且在使用了auto release pool后,连“临时对象”的释放也自动化了。可是出来混总是要还的,retain了就要release :)


当然解决办法总是有的,shared ptr 就可以搞定。shared ptr 是一种smart ptr,具体实现不罗嗦了,核心思想是每个shared ptr实例都会持有对象的一个引用(当然这不是绝对的,因为允许有不引用对象的shared ptr存在)。shared ptr被赋值时会减去当前对象的引用(如果已经引用了某对象),并增加新对象的引用。一个对象可能被存在于很多地方不同作用域中的shared ptr所引用,咋一看这挺乱的,其实理解起来很简单,只要这些ptr都销毁了,或者主动释放了引用,这个对象就会被自动释放。而其中,最关键之处在于shared ptr都是以一个对象存在的(而不是一个指针)。无论他是某某对象的成员,或者是在一个函数的栈上产生,他是一个对象而不是一个指针,所以他离开作用域时自动销毁,所以你就不用去release什么引用计数了。

回到auto release pool解决的问题,如果使用shared ptr,负责产生对象的类只需要返回这个对象的shared ptr即可,而自己不用保存该对象。如果对象使用者只是临时用一下这个对象,那用完就好了,因为shared ptr在离开作用域时自动销毁了对象。如果对象使用者需要较长时间的使用对象,那么他就用一个shared ptr来保存这个对象,如果这个对象只需要在他自己释放时释放,这个shared ptr就可以作为他的数据成员,从而不需要主动释放。如果需要提前释放对象,可以清空这个shared ptr。


可以看到,shared ptr可以完成auto release pool的功能,并且不需要维护一个pool,区别在于“临时对象”是不用的时候立刻释放的,不需要等到帧结束时。这儿不讨论两种方式在效率和内存方面的优劣,使用shared ptr会更优雅一些,并且更容易使用。当然,说到效率,智能指针肯定要比原生指针要弱,不过如果真的在某某算法里面,需要大量的指针操作,完全可以从智能指针里面get出raw pointer来使用。其他的情况,好吧,这么省事的东西总要有些代价吧,况且根据28原理,先去解决其他问题吧。


回来再说cocos2d-x,其实在其上面实现shared ptr是很容易的,因为CCObject本身已经有了管理引用计数的功能,因此自己实现一个shared ptr的类模板,去管理CCObject类体系中的类也是很轻松的。当然如果你对boost有爱,使用他的非侵入式智能指针 intrusive_ptr 也是可以的。我觉得cocos2d-x的使用者们,不妨一试~






更多详细信息请查看java教程网 http://www.itchm.com/forum-59-1.html
分享到:
评论

相关推荐

    采用引用计数的智能指针share_ptr

    采用引用计数的智能指针share_ptr,可以用于标准库容器

    C++ 智能指针(shared_ptr/weak_ptr)源码

    C++ 智能指针(shared_ptr/weak_ptr)源码 源码位置:gcc-6.1.0\gcc-6.1.0\libstdc++-v3\include\tr1 这里只单列shared_ptr.h文件用于分析

    C++仿写指针指针(auto-ptr,unique-ptr,shared-ptr,weak-ptr)

    智能指针其实是一个类,是对普通指针进行了封装,将其作为参数传入智能指针的构造函数实现绑定。... auto ptr, 2. unique ptr, 3. shared ptr, 4. weak ptr 下面的代码对这四个智能指针进行一一仿写:

    shared_ptr for arm

    shared_ptr arm, use arm asm code

    C++智能指针:shared-ptr用法详解.pdf

    C++智能指针:shared_ptr⽤法详解 C++智能指针:shared_ptr⽤法详解 shared_ptr是C++11⾥的新特性,其包装了new操作符在堆上分配的动态对象。如: shared_ptr<int> sp1(new int(100)); //相当于 //int *sp1=new int...

    C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)

    当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1。当shared_ptr离开作用域时,引用计数减1。当引用计数为0时,释放所管理的内存。 这样做的好处在于解放了程序员手动释放内存的压力。之前...

    C++智能指针shared-ptr讲解与使用.pdf

    引⽤计数指的是,所有管理同⼀个裸指针( raw pointer )的 shared_ptr,都共享⼀个引⽤计数器,每当⼀个 shared_ptr 被赋值(或拷贝构造)给其它 shared_ptr 时,这个共享的引⽤计数器就加 1,当⼀个 shared_ptr ...

    智能指针shared-ptr的用法.pdf

    shared_ptr使⽤引⽤计数,每⼀个shared_ptr的拷贝都指向相同的内存。每使⽤他⼀次,内部的引⽤计数加1,每析构⼀次,内部的引⽤ 计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引⽤计数是安全的,但是...

    shared-ptr(智能指针)举例.pdf

    shared_ptr(智能指针)举例 程序使⽤动态内存出于以下三种原因之⼀ : 1、程序不知道⾃⼰需要多少对象;... ⼀般采⽤auto定义⼀个对象来保存make_shared的结果,如 auto p2 = std::make_shared(88); 例

    shared_ptr

    shared_ptr boost audio video AVDataPool

    智能指针shared-ptr的初始化.pdf

    智能指针 智能指针shared_ptr的初始化 的初始化 shared_ptr是智能指针,是模板,头⽂件是memory: shared_ptr<string> p1 最安全的使⽤⽅法是调⽤make_shared标准库函数,此函数在动态内存中分配⼀个对象并初始化它...

    智能指针shared_ptr的Demo

    这是一个演示智能指针shared_ptr的一个Demo。本代码所对应的博客地址为https://blog.csdn.net/wfh2015/article/details/80699378

    C++ unique_ptr weak_ptr shared_ptr auto_ptr智能指针.doc

    四种智能指针的使用、机制和缺陷分析

    C++11 std::shared_ptr总结与使用示例代码详解

    (3) 在赋值操作中, 原来资源的引用计数会减一,新指向的资源引用计数会加一。 std::shared_ptr<Test> p1(new Test); std::shared_ptr<Test> p2(new Test); p1 = p2; (4) 引用计数加一/减一操作是原子性的,所

    weak-ptr 和 shared-ptr 源码

    关于C++智能指针 weak_ptr (弱引用 智能指针) 和 shared_ptr (强引用 智能指针)的源文件。 资源分不能设为0了。。

    详解C++中shared_ptr的使用教程

    shared_ptr是一种智能指针(smart pointer)。shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。 这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是...

    C++11 智能指针之shared_ptr代码详解

    C++中的智能指针首先出现在“准”标准...shared_ptr是一个引用计数智能指针,用于共享对象的所有权也就是说它允许多个指针指向同一个对象。这一点与原始指针一致。 先来一段简单的代码,看看shared_ptr的简单使用: #

    用shared_ptr实现多线程对全局变量的读写,copy-on-write技术

    参考陈硕的多线程服务端编程>>,中的用shared_ptr实现copy-on-write技术,不过这里的线程采用的是c++11的线程库

    C++智能指针shared_ptr分析

    它采取引用计数的方法来实现释放指针所指向的资源。下面是我代码实现的基本功能。 实例代码: template class sharedptr { public: sharedptr(T* ptr) :_ptr(ptr) , _refCount(new int(1)) {} sharedptr...

    shared_ptr线程安全性全面分析

    本文基于shared_ptr的源代码,提取了shared_ptr的类图和对象图,然后分析了shared_ptr如何保证文档所宣称的线程安全性。本文的分析基于boost 1.52版本,编译器是VC 2010。 shared_ptr的线程安全性boost官方文档对...

Global site tag (gtag.js) - Google Analytics