原创作品,转载请标明http://blog.csdn.net/jackystudio/article/details/13765639

再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的属性和方法后,CCObject还剩下什么?

1.剩下什么?

可以看到整个CCObject就是围绕着m_uReference和m_uAutoReleaseCount在转。这两个变量的解释如下。所以CCObject剩下的其实就是对内存的管理。

  1. CCObject::CCObject(void)//构造函数
  2. : m_nLuaID(0)
  3. , m_uReference(1) //引用计数,初始为1,当引用计数=0,自动释放该对象
  4. , m_uAutoReleaseCount(0)//自动释放对象计数,如果是手动new的,则为0,如果autoRelease的,则在AutoreleasePool会+1
  5. //这里是保护成员,所以CCAutoreleasePool被声明为友元类
  6. {
  7. static unsigned int uObjectCount = 0;//静态成员,对象的计数,只增不减,用于标识唯一一个对象实例
  8. m_uID = ++uObjectCount;
  9. }
  10.  
  11. CCObject::~CCObject(void)
  12. {
  13. if (m_uAutoReleaseCount > 0)//如果是自动管理,则在PoolManager中删除
  14. {
  15. CCPoolManager::sharedPoolManager()->removeObject(this);
  16. }
  17.  
  18. // if the object is referenced by Lua engine, remove it
  19. if (m_nLuaID)
  20. {
  21. CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(this);
  22. }
  23. else
  24. {
  25. CCScriptEngineProtocol* pEngine = CCScriptEngineManager::sharedManager()->getScriptEngine();
  26. if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript)
  27. {
  28. pEngine->removeScriptObjectByCCObject(this);
  29. }
  30. }
  31. }
  32.  
  33. void CCObject::release(void)//引用计数-1,如果引用计数=0,释放对象
  34. {
  35. CCAssert(m_uReference > 0, "reference count should greater than 0");
  36. --m_uReference;
  37.  
  38. if (m_uReference == 0)
  39. {
  40. delete this;
  41. }
  42. }
  43.  
  44. void CCObject::retain(void)//引用计数+1,防止被对象释放
  45. {
  46. CCAssert(m_uReference > 0, "reference count should greater than 0");
  47.  
  48. ++m_uReference;
  49. }
  50.  
  51. CCObject* CCObject::autorelease(void)//对象加入PoolManager,自动管理
  52. {
  53. CCPoolManager::sharedPoolManager()->addObject(this);
  54. return this;
  55. }
  56.  
  57. bool CCObject::isSingleReference(void) const //返回是否唯一引用
  58. {
  59. return m_uReference == 1;
  60. }
  61.  
  62. unsigned int CCObject::retainCount(void) const //返回引用计数
  63. {
  64. return m_uReference;
  65. }
  66.  
  67. bool CCObject::isEqual(const CCObject *pObject) //判断对象是否相等
  68. {
  69. return this == pObject;
  70. }
  71.  
  72. void CCObject::acceptVisitor(CCDataVisitor &visitor) //辅助对象执行动作
  73. {
  74. visitor.visitObject(this);
  75. }

2.内存管理

从CCObject可以看出,内存的管理方式有两种:手动管理和自动管理。

2.1.手动内存管理

想必从Java转到C++的朋友可能很受不了C++再申请完内存后还要手动释放,就像我从C++转Java时也同样很不习惯竟然不用管理内存,老是害怕会不小心让系统给销毁了。CCObject的成员变量m_uAutoReleaseCount标识了是手动管理还是自动管理。如果执行以下操作:

  1. CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1

从析构函数可以看到,析构函数是不对所有手动进行申请的变量进行内存释放(必须m_uAutoReleaseCount>0)。那么这时得手动释放:

  1. obj->release();//m_uReference-1后为0,执行delete this;

所以,new和release是好基友!而手动内存管理一般不再使用retain。

2.2.自动内存管理

如果需要进行内存的自动管理,那要怎么做呢?

  1. CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1
  2. obj->autorelease();//m_uAutoReleaseCount=1,m_uReference=1

好了,什么都不用做,obj自生自灭了。

如果我们需要随时用到obj,而不愿意让它在我们不知情的情况下被释放,那么使用:

  1. obj->retain();//m_uAutoReleaseCount=1,m_uReference=2

当不再需要它的时候,使用:

  1. obj->release();//m_uAutoReleaseCount=1,m_uReference=1

又恢复回去了,所以,retain和release是好基友,一般在自动内存管理使用。


这里只是大概写一下如何使用new,autorelease,retain和release,至于内存管理的实现网上的代码解析很多,发现自己没办法深入浅出地写出来,所以还是放弃再写一回注释了,原理可以这么理解:Cocos2d-x提供了一个内存管理器类CCPoolManager,它包含了一个CCArray容器m_pReleasePoolStack,这个容器用来存放一些容器管理类CCAutoreleasePool的实例对象。需要自动进行内存释放的CCObject实例对象会把其指针存放在容器管理类CCAutoreleasePool的实例对象中的m_pManagedObjectArray容器里。所有存在其中的CCObject实例对象在进行释放操作时通过使用计数器来进行判断在何时真正释放内存,游戏在每一帧结束时都会对autorelease对象进行释放。

2.3.一个疑问

平时我们可能会这么用:

  1. //CTestLayer.h
  2. class CTestLayer : public cocos2d::CCLayer
  3. {
  4. public:
  5. virtual bool init();
  6.  
  7. CREATE_FUNC(CTestLayer);
  8.  
  9. virtual void update(float delta);
  10.  
  11. private:
  12. CCSprite* background;
  13. };
  14.  
  15. //CTestLayer.cpp
  16. bool CTestLayer::init()
  17. {
  18. if ( !CCLayer::init() )
  19. {
  20. return false;
  21. }
  22. background=CCSprite::create("background.png");
  23. this->addChild(background);
  24. this->scheduleUpdate();
  25. return true;
  26. }
  27.  
  28. void update(float delta)
  29. {
  30. background->setPositionY(background->getPositionY()-0.1);
  31. }

background是create出来的,可以知道它是调用了autorelease,属于自动管理对象,而且我们又没有进行retain操作,按道理在执行update的时候background已经是要被销毁的,但是实际并没有。问题就出在这一句:

  1. this->addChild(background);

至于为什么,大家翻一下addChild实现源码就知道啦~

[置顶] 【玩转cocos2d-x之二十】从CCObject看cocos2d-x的内存管理机制的更多相关文章

  1. 你必须了解的java内存管理机制(二)-内存分配

    前言 在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式. 相关链接(注:文章讲解 ...

  2. [置顶] c#验证码识别、图片二值化、分割、分类、识别

    c# 验证码的识别主要分为预处理.分割.识别三个步骤 首先我从网站上下载验证码 处理结果如下: 1.图片预处理,即二值化图片 *就是将图像上的像素点的灰度值设置为0或255. 原理如下: 代码如下: ...

  3. [置顶] xamarin android使用zxing扫描二维码

    好久没写了,这片文章篇幅不长,概述一下在xamarin android中用 ZXing.Net.Mobile库扫描二维码读取url的示例.扫码支付,扫码登录,App上各种各样的扫码,好像没个扫码的就有 ...

  4. [置顶] 玩转Eclipse — 自动注释插件JAutodoc

    代码注释是一种良好的编程习惯.不管对于他人还是自己,注释都有助于代码的阅读和理解.手动添加注释,是一个非常费时和繁琐的工作,严重影响软件开发效率,这也是绝大多数程序员不愿添加注释的主要原因.JAuto ...

  5. [置顶] Hibernate从入门到精通(十)多对多单向关联映射

    上一篇文章Hibernate从入门到精通(九)一对多双向关联映射中我们讲解了一下关于一对多关联映射的相关内容,这次我们继续多对多单向关联映射. 多对多单向关联映射 在讲解多对多单向关联映射之前,首先看 ...

  6. Java自动内存管理机制学习(二):垃圾回收器与内存分配策略

    备注:本文引自<深入理解Java虚拟机第二版>仅供参考 图片来自:http://csdn.net/WSYW126 垃圾收集器与内存分配策略 概述 GC要完成3件事: 哪些内存需要回收? 什 ...

  7. 第二百二十九节,jQuery EasyUI,后台管理界面---后台登录

    jQuery EasyUI,后台管理界面---后台登录 登录原理图 一,login.php,登录界面 <!DOCTYPE html> <html> <head> & ...

  8. 【python测试开发栈】—python内存管理机制(二)—垃圾回收

    在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...

  9. [置顶] NGINX原理分析之SLAB分配机制

    一.基础概述 如果使用伙伴系统分配和释放算法,不仅会造成大量的内存碎片,同时处理效率也比较低.SLAB是一种内存管理机制,其核心思想是预分配.SLAB是将空间按照SIZE对内存进行分类管理的,当申请一 ...

随机推荐

  1. hdoj 5120 Intersection 圆环面积求交

    Intersection Time Limit: 4000/4000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others) Tota ...

  2. 洛谷OJ P2356 弹珠游戏 维护前缀和

    题目描述 Description MedalPluS 和他的小伙伴 NOIRP 发掘了一个骨灰级别的游戏--超级弹珠. 游戏的内容是:在一个 n*n 的矩阵里,有若干个敌人,你的弹珠可以摧毁敌人,但只 ...

  3. Codeforces Round #293 (Div. 2) A. Vitaly and Strings

    A. Vitaly and Strings time limit per test 1 second memory limit per test 256 megabytes input standar ...

  4. [JAVA] JAVA 文档注释

    Java 程序设计环境 文档注释 javadoc JDK中包含的javadoc工具可以由源文件生成一个HTML文档. javadoc从以下几个特性中抽取信息 包 公有类与接口 公有的和受保护的构造器及 ...

  5. buffer and cache -systemtap

    http://blog.csdn.net/dianhuiren/article/details/7543886

  6. pig—WordCount analysis

    grunt> cat /opt/dataset/input.txt keyword1 keyword2 keyword2 keyword4 keyword3 keyword1 keyword4 ...

  7. [Javascript]XMLHttpRequest对象实现下载进度条

    摘要 可以通过设置一个XMLHttpRequest对象的responseType属性来改变一个从服务器上返回的响应的数据类型.可用的属性值为空字符串 (默认), "arraybuffer&q ...

  8. iOS开源控件库收集

    下拉刷新 将数据保存至keyRing 简单的模板引擎,用来生成html OmniGroup 这个其实不是类库,是一个Cocoa的Recipe CocoaPods 为XCode project提供一个类 ...

  9. 如何搭建 LNMP环境

    和LAMP不同的是LNMP中的N指的是是Nginx(类似于Apache的一种web服务软件)其他都一样.目前这种环境应用的也是非常之多. Nginx设计的初衷是提供一种快速高效多并发的web服务软件. ...

  10. CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能

    .启动安装在 VirtualBox 中的 CentOS 5.5 虚拟机,点击“设备” => “安装增强功能”.这个时候你就可以看到有一个“光盘”已经挂载到 CentOS 5.5 的桌面上了.它包 ...