cocos2dx的内存管理移植自Objective-C, 对于没有接触过OC的C++开发人员来说是挺迷惑的。不深入理解内存管理是无法写出好的C++程序的,我用OC和cocos2dx也有一段时间了,在此总结一下,希望对想用cocos2dx开发游戏的朋友有所帮助。
 
C++的动态内存管理一般建议遵循谁申请谁释放的原则,即谁通过new操作符创建了对象,谁就负责通过delete来释放对象。如果对象的生命周期在一个函数内,这很容易做到,在函数返回前delete就行了。但一般我们在函数中new出来的对象的生命周期都会超出该函数体(例如作为函数的返回值),否则我们可以直接在栈上创建对象,不需要使用动态内存,也省去了内存管理的麻烦(当然大对象是不适合在栈上分配的)。如果对象的生命周期超出了创建对象的函数,我们就很难再遵循谁申请谁释放的原则了,我们必须在函数外的某个合适的地方释放对象,如果这个对象同时被多个对象引用,问题就很复杂了,必须保证所有该对象的引用者都不再需要它了才可以释放,在实际使用中这点是很难保证的。于是,各种内存管理技术应运而生了:垃圾回收器,智能指针,引用计数...... cocos2dx移植于Objective-C,因此和OC一样使用了比较原始的引用计数的方法来管理内存。
 
cocos2dx通过CCObject和CCPoolManager来实现内存管理。所有使用cocos2dx引用计数机制的类都必须派生自CCObject。CCObject有一个计数器成员变量m_uReference,当CCObject被构造时m_uReference=1,表示该对象被引用1次。CCObject的retain方法可以使计数器加1,release方法可以使计数器减1。当计数器减到0时release方法会通过delete this来销毁自己。
 
手动内存管理
使用retain和release,我们可以手动管理内存, 通过new 创建的对象,使用release来释放。
CCObject *obj=new CCObject();
...
obj->release();

和new\delete需配对使用一样,new\release也要配对使用才可确保内存被释放。有人会说这个把delete换成release有意义吗?需要注意的是这个的release并不等同于delete,release只是表示引用计数减1,并不是真正销毁obj所占用的内存。只有当obj的引用计数为0时内存才会被销毁。下面的代码就展示了release和delete不同:

CCArray *array = CCArray::array();
CCObject *obj = new CCObject();// m_uReference=1
array->addObject(obj); // CCArray的addObject方法会自动调用obj的retain方法,使引用计数加1,表示拥有obj,此时m_uReference=2
obj->release(); // 这里的release和new配对,obj引用计数减1,但是并不会释放obj, 此时m_uReference=1;
obj->doSomething(); // 在release之后我们依然可以正常使用obj,它并没有被释放
array->removeObject(obj); //当我们把obj从CCArray中移除时,CCArray会自动调用obj的release,此时m_uReference=0, obj被销毁
obj->doSomething(); // 错误,obj已经被销毁

对于手动内存管理,我们需遵循new/release,retain/release配对使用的原则,谁new,谁release;谁retain,谁release。new出来的对象如果是要加入到cocos2dx集合中,添加完后一定不要忘记release,集合类已经为你retain了对象,你还是要为你的new配对release一次,否则当这个对象从集合中移除时不会被正确销毁。

 
自动内存管理
手动内存管理似乎比new/delete更麻烦,而且并没有解决一开始我们提到的函数内创建的对象的生命周期超出函数怎么办的问题。new和release需配对使用,那在函数内创建的对象返回前我们需要调用一次release,在这之前如果我们没有把对象加入到什么集合中,对象就被销毁了,和使用new/delete是一样的。自动内存管理就可以解决这个问题。CCObject有一个autorelease方法,如果一个对象在用new关键字创建之后调用了autorelease,我们就不必关心它的释放问题。CCPoolManager会在游戏的每一帧结束后自动释放这些autorelease的对象。CCPoolManager其实依然是通过引用计数来管理对象生命周期的,它里面有一个CCAutoreleasePool,我们调用CCObject的autorelease就是把自己加入到CCAutoreleasePool的对象数组里面。当每一帧结束的时候,CCPoolManager会将对象从数组中移除,如果这时候对象的引用计数为0,对象就自然被释放了。对于用new关键字创建之后调用了autorelease的对象,不需要再release一次。
 
cocos2dx中的大部分对象都可以通过静态工厂方法来创建出这种会自动释放的对象,这是cocos2dx的一条规则,我们自己实现的类最好也遵循这样的规则,以免引起其他开发人员误会。如果一个对象是通过类的静态方法创建而不是new出来的,我们就不需要release它。
 
其实这里的自动并没有我们想得那么好,对于像C#,Java这种托管语言,虚拟机为你完成了所有内存管理工作,程序员完全从内存分配和释放中解脱了出来。cocos2dx的autorelease只不过每帧结束后自动在为我们释放了一次对象,如果我们希望创建的对象在下一帧仍然可以使用,我们需要显式地retain一下这个对象或者把对象加入到集合中(集合会帮我们retain一次)。既然retain了,我们还是不能忘记在适当的地方release。比较常见的用法是创建一个autorelease对象作为类成员变量,我们在通过静态方法得到实例的指针后除了赋值给类成员,还要retain一次,然后在类的析构函数中release一次。如果没有retain,以后使用该成员的时候就会因为对象被销毁而发生内存访问错误,这是新手很容易遇到的陷阱。

(转)cocos2dx 内存管理的更多相关文章

  1. cocos2d-x内存管理

    Cocos2d-x内存管理 老师让我给班上同学讲讲cocos2d-x的内存管理,时间也不多,于是看了看源码,写了个提纲和大概思想 一.   为什么需要内存管理 1. new和delete 2. 堆上申 ...

  2. cocos2dx内存管理的一些看法

    今年年初进入一家游戏公司,正式开始游戏引擎的学习,之前的ios学习,对现在的游戏引擎学习还是有很大的帮助的,虽然使用c++,但却能时刻感受到ios框架对于cocos2dx的巨大影响. 由于之前一直使用 ...

  3. 2、COCOS2D-X内存管理机制

    在C++中.动态内存分配是一把双刃剑,一方面,直接訪问内存地址提高了应用程序的性能,与使用内存的灵活性.还有一方面.因为程序没有正确地分配与释放造成的比如野指针,反复释放,内存泄漏等问题又严重影响着应 ...

  4. cocos2dx内存管理机制

    参考以下两篇文章 http://blog.csdn.net/ring0hx/article/details/7946397 http://blog.csdn.net/whuancai/article/ ...

  5. cocos2d-x内存管理(见解)

    cocos2d-x 延续了cocos2d 和OC的引用计数的内存管理机制! 下面我们来看看CCDriectro类 CCPoolManager::sharedPoolManager()->push ...

  6. cocos2d-x 内存管理浅析

    Cocos2d-x用create创建对象, 这个方法已经被引擎封装成一个宏定义了:CREATE_FUNC, 下面是这个宏定义的实现: #define CREATE_FUNC(__TYPE__) \   ...

  7. cocos2dx 内存管理的理解

    关于引擎内存管理的细节,网上有大量的详解,这里概括一下: cocos2d-x 的世界是基于 CCObject 类构建的,所以内存管理的本质就是管理一个个 CCObject. //CCObject 内部 ...

  8. cocos2dx 内存管理

    转载自 ocos2dx 内存管理 - 小花原创博客 - 博客频道 - CSDN.NET http://blog.csdn.net/ring0hx/article/details/7946397 coc ...

  9. Cocos2d-x内存管理研究<二>

    http://hi.baidu.com/tzkt623/item/46a26805adf7e938a3332a04   上一篇我们讲了内核是如何将指针加入管理类进行管理.这次我将分析一下内核是如何自动 ...

  10. Cocos2d-X内存管理研究<一>

    http://hi.baidu.com/tzkt623/item/651ca7d7a0aff6e055347f67        半夜没事干,研究内核,作为我cocos2d-x的第一篇教程.cocos ...

随机推荐

  1. iOS适配:Masonry介绍与使用实践:快速上手Autolayout

    随着iPhone的手机版本越来越多, 那么对于我们广大的开发者来说就是很悲催,之前一直使用代码里面layout的约束来适配, 现在推荐一个第三方Masonry,上手块,操作简单,只能一个字形容他 “爽 ...

  2. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  3. bzoj2096: [Poi2010]Pilots

    Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是 ...

  4. /proc/sys/net/ipv4/ip_forward

    ip地址分公有地址和私有地址,public address是由INIC(internet network information center)负责,这些ip地址分配给注册并向INIC提出申请的组织机 ...

  5. iOS的app 中的 埋点

    埋点 就是 挖个坑把 种子埋到土里 然后浇水  等待发芽 埋点就是 ,鬼子要进村,我们埋下地雷 埋点就是 小说中 作者欲扬先抑  或者欲擒故纵  设下的伏笔... 好了,用文学的手法很好的  解释了一 ...

  6. pycharm console 控制台乱码的解决

  7. 均值,方差: 概率质量函数PMF

    __author__ = 'dell' import Pmf import matplotlib.pyplot as pyplot pmf = Pmf.MakePmfFromList([1, 2, 2 ...

  8. 关于新手与SEO误区的那些事儿

    常见的SEO误区,部落觉得对于新手来说,最容易出现问题的就是关健词堆砌了.记得部落自己最开始做网站的时候,基本每一篇文章都会布局很密的关健词.当然,对于新手网站SEO来说,远远不止这一点,或许最重要的 ...

  9. STM32F10x 学习笔记5(USART实现串口通讯 1)

    STM32F10x 系列单片机中都包含了USART 模块,所谓USART,就是通用同步异步收发器.通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间 ...

  10. 连接各种数据库神器———DbVisualizer

    作为开发人员,经常会遇到在不同的数据库环境中进行开发或者调试,所以针对每种数据库都要安装对应的客户端,不但要占用硬盘控件而且还要经常切换,无可厚非这是一项头疼并且麻烦的事情.有了DbVisualize ...