想起这个话题,是因为最近在研究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,可以用于标准库容器
此外,`shared_ptr`还支持拷贝构造和赋值操作,拷贝或赋值时,所有`shared_ptr`实例都会共享同一个引用计数,这样可以确保只有在没有`shared_ptr`指向目标对象时才释放内存。 在C++中,`shared_ptr`通常用于替代...
`shared_ptr`的构造、赋值、解引用、比较操作等方法都涉及到对这个引用计数的管理和对象的生命周期控制。 `weak_ptr`的实现通常会包含一个`shared_ptr`的内部表示,但不增加其引用计数。`weak_ptr`的`lock`方法用于...
shared_ptr 的机制是通过计数器管理引用同一个指针的指针实例对象的个数,实现多个对象共享同一块内存。 四、weak_ptr weak_ptr 是 C++11 中引入的智能指针,它可以管理动态分配的内存,并允许多个实例共享同一块...
`shared_ptr`解决了这些问题,它通过内部的引用计数机制来跟踪有多少个`shared_ptr`实例在指向同一个对象。当一个`shared_ptr`被创建或复制时,引用计数增加;当`shared_ptr`被销毁或赋值给其他`shared_ptr`时,引用...
2. `std::shared_ptr`:共享式拥有,使用引用计数机制。多个`std::shared_ptr`可以同时指向同一对象,当最后一个`std::shared_ptr`析构时,会自动删除对象。`std::shared_ptr`可以通过`std::make_shared`创建,以...
引用计数是一种常见的内存管理策略,特别是在C++中,它被用于智能指针类,如`std::shared_ptr`和`std::weak_ptr`。在本项目中,我们看到一个用C++实现的引用计数系统,这个系统可能是为了自定义的智能指针或者对象...
`shared_ptr`维护了一个内部的引用计数,记录有多少个`shared_ptr`实例指向同一对象。当计数减少到零时,对象会被销毁。`use_count()`函数返回这个引用计数: ```cpp cout 当前计数: " () ; ``` 在多个`shared_ptr`...
C++ 智能指针(shared_ptr/weak_ptr)源码 源码位置:gcc-6.1.0\gcc-6.1.0\libstdc++-v3\include\tr1 这里只单列shared_ptr.h文件用于分析
其中`shared_ptr`是C++11引入的一种智能指针,它遵循引用计数的策略来管理内存。`shared_ptr`是模板类,位于`<memory>`头文件中,可以用来持有任何类型的裸指针。 ### shared_ptr 的初始化 初始化`shared_ptr`最...
智能指针其实是一个类,是对普通指针进行了封装,将其作为参数传入智能指针的构造函数实现绑定。... auto ptr, 2. unique ptr, 3. shared ptr, 4. weak ptr 下面的代码对这四个智能指针进行一一仿写:
引用计数是COM实现对象生命周期管理的关键机制,尤其在内存管理方面起到重要作用。 引用计数的基本原理是,每当一个客户端(如另一个对象或程序)获得对COM对象的引用时,该对象的引用计数就会增加1;当客户端不再...
在C++标准库中,`std::shared_ptr`(在早期版本中可能使用`boost::shared_ptr`)是一种智能指针,它通过引用计数来管理动态分配的对象生命周期。`std::shared_ptr`的设计目的是自动管理对象的内存,当最后一个指向该...
`shared_ptr`遵循引用计数的机制,当最后一个拥有该对象的`shared_ptr`被销毁时,对象也会被删除。这样就避免了手动管理内存的麻烦。 例如,要使用`shared_ptr`托管一个动态分配的对象,我们可以这样做: ```cpp ...
std::shared_ptr是其中的一种,它使用引用计数机制来跟踪指向同一对象的智能指针数量。每当一个shared_ptr被创建或者复制,对象的引用计数就会增加;当一个shared_ptr被销毁或者reset,引用计数会减少。当引用计数降...
`shared_ptr`是一种引用计数智能指针,当一个`shared_ptr`对象指向一个资源时,它会记录有多少个`shared_ptr`对象共享这个资源,当最后一个`shared_ptr`对象不再指向该资源时,该资源会被自动释放。这是通过引用计数...
shared_ptr arm, use arm asm code
当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1。当shared_ptr离开作用域时,引用计数减1。当引用计数为0时,释放所管理的内存。 这样做的好处在于解放了程序员手动释放内存的压力。之前...