从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实现源码就知道啦~

相关文章
|
1月前
|
监控 算法 Java
如何确保Python的内存管理机制能够有效地工作?
【2月更文挑战第19天】【2月更文挑战第57篇】如何确保Python的内存管理机制能够有效地工作?
|
1月前
|
存储 Java Python
谈谈你对 Python 的内存管理机制的理解。
【2月更文挑战第19天】【2月更文挑战第55篇】谈谈你对 Python 的内存管理机制的理解。
|
21天前
|
存储 缓存 Java
金石原创 |【JVM盲点补漏系列】「并发编程的难题和挑战」深入理解JMM及JVM内存模型知识体系机制(1)
金石原创 |【JVM盲点补漏系列】「并发编程的难题和挑战」深入理解JMM及JVM内存模型知识体系机制(1)
34 1
|
5月前
|
存储 Cloud Native Linux
C++ vector内存增长机制
C++ vector内存增长机制
|
29天前
|
监控 安全 算法
深入理解操作系统的内存管理机制
【2月更文挑战第30天】 本文旨在探讨操作系统中至关重要的一环——内存管理。与传统摘要不同,本文将直接点出核心议题:操作系统是如何通过复杂的数据结构和算法实现对计算机内存的有效管理和优化。文章将详细阐述内存管理的关键组成部分,包括内存分配、虚拟内存技术、分页和段机制等,并探讨它们如何共同协作以支持多任务处理和保护系统安全。通过对这些机制的深入了解,读者可以更好地把握操作系统设计之精髓及对现代计算环境的深远影响。
|
2天前
|
存储 算法 数据安全/隐私保护
深入理解操作系统的内存管理机制
【4月更文挑战第17天】 在现代计算机系统中,操作系统扮演着资源管理者的角色,其中内存管理是其核心职能之一。本文探讨了操作系统内存管理的关键技术,包括虚拟内存、物理内存分配与回收、分页和分段机制,以及内存交换技术。通过分析这些机制的原理和实现,我们旨在加深读者对操作系统如何有效管理和保护内存资源的理解。
6 1
|
4天前
|
算法
深入理解操作系统的内存管理机制
【4月更文挑战第15天】 本文将探讨操作系统中至关重要的一环——内存管理。不同于通常对内存管理概念的浅尝辄止,我们将深入研究其核心原理与实现策略,并剖析其对系统性能和稳定性的影响。文章将详细阐述分页系统、分段技术以及它们在现代操作系统中的应用,同时比较它们的效率与复杂性。通过本文,读者将获得对操作系统内存管理深层次工作机制的洞见,以及对设计高效、稳定内存管理系统的理解。
|
14天前
|
缓存 监控 算法
深入理解操作系统的内存管理机制
【4月更文挑战第5天】 随着现代计算机系统的发展,操作系统的内存管理已成为确保系统高效稳定运行的关键因素。本文旨在探讨操作系统中内存管理的基本原理、关键技术及其在实际应用中的优化策略。通过分析内存分配、虚拟内存技术以及内存保护和分页机制等方面,揭示内存管理对提升系统性能的重要性,并提供了一系列优化内存使用效率的方法。
|
30天前
|
NoSQL 应用服务中间件 Linux
Redis的内存回收机制
Redis的内存回收机制
24 2
|
30天前
|
算法 UED
深入理解操作系统的内存管理机制
【2月更文挑战第29天】 在现代计算机系统中,操作系统扮演着至关重要的角色,尤其在内存资源的分配与管理上。本文将详细探讨操作系统内存管理的关键技术和策略,包括分页、分段、虚拟内存以及物理内存的管理。通过剖析这些机制的原理与实现,旨在为读者提供一个清晰的框架,以理解操作系统如何高效地处理内存资源,确保系统的稳定运行及良好的用户体验。