从CCObject看cocos2d-x的内存管理机制

简介: <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px; line-height:26px"> <span style="font-family:'Microsoft YaHei'">再看CCObject,剔除上节

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


1.剩下什么?

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

[cpp]  view plain copy
  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(voidconst //返回是否唯一引用  
  58. {  
  59.     return m_uReference == 1;  
  60. }  
  61.   
  62. unsigned int CCObject::retainCount(voidconst  //返回引用计数  
  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标识了是手动管理还是自动管理。如果执行以下操作:

[cpp]  view plain copy
  1. CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1  
从析构函数可以看到,析构函数是不对所有手动进行申请的变量进行内存释放(必须m_uAutoReleaseCount>0)。那么这时得手动释放:

[cpp]  view plain copy
  1. obj->release();//m_uReference-1后为0,执行delete this;  
所以,new和release是好基友!而手动内存管理一般不再使用retain。

2.2.自动内存管理

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

[cpp]  view plain copy
  1. CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1  
  2. obj->autorelease();//m_uAutoReleaseCount=1,m_uReference=1  

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

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

[cpp]  view plain copy
  1. obj->retain();//m_uAutoReleaseCount=1,m_uReference=2  
当不再需要它的时候,使用:

[cpp]  view plain copy
  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.一个疑问

平时我们可能会这么用:

[cpp]  view plain copy
  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已经是要被销毁的,但是实际并没有。问题就出在这一句:

[cpp]  view plain copy
  1. this->addChild(background);  

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

相关文章
|
2月前
|
存储 监控 算法
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,着重介绍垃圾回收(Garbage Collection, GC)机制。通过阐述GC的工作原理、常见算法及其在Java中的应用,帮助读者提高程序的性能和稳定性。我们将从基本原理出发,逐步深入到调优实践,为开发者提供一套系统的理解和优化Java应用中内存管理的方法。
|
3月前
|
监控 算法 Java
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,特别是垃圾回收(Garbage Collection, GC)机制。我们将从基础概念开始,逐步解析垃圾回收的工作原理、不同类型的垃圾回收器以及它们在实际项目中的应用。通过实际案例,读者将能更好地理解Java应用的性能调优技巧及最佳实践。
103 0
|
1月前
|
存储 算法 Java
Go语言的内存管理机制
【10月更文挑战第25天】Go语言的内存管理机制
29 2
|
1月前
|
存储 运维 Java
💻Java零基础:深入了解Java内存机制
【10月更文挑战第18天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
35 1
|
2月前
|
存储 安全 NoSQL
driftingblues9 - 溢出ASLR(内存地址随机化机制)
driftingblues9 - 溢出ASLR(内存地址随机化机制)
42 1
|
3月前
|
消息中间件
共享内存和信号量的配合机制
【9月更文挑战第16天】本文介绍了进程间通过共享内存通信的机制及其同步保护方法。共享内存可让多个进程像访问本地内存一样进行数据交换,但需解决并发读写问题,通常借助信号量实现同步。文章详细描述了共享内存的创建、映射、解除映射等操作,并展示了如何利用信号量保护共享数据,确保其正确访问。此外,还提供了具体代码示例与步骤说明。
|
2月前
|
程序员 编译器 数据处理
【C语言】深度解析:动态内存管理的机制与实践
【C语言】深度解析:动态内存管理的机制与实践
|
4月前
|
JavaScript 前端开发 算法
js 内存回收机制
【8月更文挑战第23天】js 内存回收机制
41 3
|
4月前
|
存储 JavaScript 前端开发
学习JavaScript 内存机制
【8月更文挑战第23天】学习JavaScript 内存机制
39 3
|
4月前
|
存储 缓存 编译器
Linux源码阅读笔记06-RCU机制和内存优化屏障
Linux源码阅读笔记06-RCU机制和内存优化屏障