上一篇文件讲到了CCObject中实现的内存自动管理内存

下面介绍两个很重要的类,一个是内存池类 CCAutoReleasePool ,另一个类是内存池管理类 CCPoolManager

这两个类结合在一起使用.

先看一下CCAutoReleasePool类,这个类其实就是对 CCArray的一个封装,把需要自动释放的对象,都添加到此类的成员变量m_pManagedObjectArray中

CCAutoReleasePool类的定义如下.还是直接在注释中解释比较方便,直接看注释吧.

 //内存池,其实就是一个CCArray的封装
class CC_DLL CCAutoreleasePool : public CCObject
{ CCArray* m_pManagedObjectArray;
public:
CCAutoreleasePool(void);
~CCAutoreleasePool(void); //向内存池添加一个对象
void addObject(CCObject *pObject); //删除内存池中的pObject对象
void removeObject(CCObject *pObject); //清空内存池中所有的对象
void clear();
};
CCAutoreleasePool 类中主要就3个函数,addObject函数,向内存池中添加一个自动释放的对象的指针. removeObject函数,向内存中把pObject这个对象删除 
最后一个clear函数,把内存池中所有的对象都释放掉
此类需要结合CCPoolManager使用
再看下 CCAutoReleasePool 类的实现文件,看注释,代码如下
CCAutoreleasePool::CCAutoreleasePool(void)
{
m_pManagedObjectArray = new CCArray(); //新建一个内存池,其实就是一个数组,里面存放的元素都是需要自动释放的内存的对象
m_pManagedObjectArray->init(); //初始化内存池
} CCAutoreleasePool::~CCAutoreleasePool(void)
{
CC_SAFE_DELETE(m_pManagedObjectArray); //释放内存池
} void CCAutoreleasePool::addObject(CCObject* pObject)
{
m_pManagedObjectArray->addObject(pObject);//向内存池中添加一个对象pObject,引用计数加 1 CCAssert(pObject->m_uReference > , "reference count should be greater than 1");
++(pObject->m_uAutoReleaseCount); //自动释放内存的标识 ++ ,++后就大于0了,就表明此对象会自动释放内存,具体在哪释放,后面文章会介绍
pObject->release(); // 因为向内存池中添加对象的时候,引用计数已经加1了,所以再减1
} //释放对象pObject的内存
void CCAutoreleasePool::removeObject(CCObject* pObject)
{
//如果对象pObject的自动释放标识大于0,则将对象pObject从内存池中删除掉
for (unsigned int i = ; i < pObject->m_uAutoReleaseCount; ++i)
{
//将对象pObject从内存池中删除掉
m_pManagedObjectArray->removeObject(pObject, false);
}
} //清理内存池
void CCAutoreleasePool::clear()
{
//如果内存池中的元素个数大于0
if(m_pManagedObjectArray->count() > )
{
//CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
int nIndex = m_pManagedObjectArray->count() - ; //内存池中,也就是数组的最后一个元素的索引
#endif //下面是遍历数组,就是上次文章讲到的数组遍历的反序遍历,就是从尾部向头部的顺序进行遍历
//把内存池中所有的元素的自动释放标识都减1
CCObject* pObj = NULL;
CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)
{
if(!pObj)
break; --(pObj->m_uAutoReleaseCount); //自动释放内存标识减1
//(*it)->release();
//delete (*it);
#ifdef _DEBUG
nIndex--; //最后一个元素的索引位置也跟着减1
#endif
} //删除内存池中所有的元素
m_pManagedObjectArray->removeAllObjects();
}
}

以上是CCAutoReleasePool类的所有源码的解析,通过解析可以看出,CCAutoReleasePool就是封装了一个CCArray的一个对象,用一个数组存放所有的自动释放内存的对象

这个类需要和 CCPoolManager在结合使用,CCPoolManager从名字可以知道,是内存池管理器.专门用来管理内存池的.

CCPoolManager使用一个CCArray来封装了一个栈结构,栈顶为数组的最后一个元素,栈底为第一个元素.栈中所有的元素其实就是一个内存池.

可见CCAutoReleasePool需要和CCPoolManager结合来使用

与上面一样,直接发代码,源码里面都有清楚的注释,先看CCPoolManager的类定义,源码如下

class CC_DLL CCPoolManager
{
CCArray *m_pReleasePoolStack; //栈
CCAutoreleasePool *m_pCurReleasePool; //栈顶元素 CCAutoreleasePool* getCurReleasePool(); //获得当前的栈顶元素
public:
CCPoolManager(); //构造函数
~CCPoolManager(); //析造函数
void finalize(); //清理栈内存的工作,栈中每个元素都是一个内存池,此函数将栈中每个内存池的内存都释放掉
void push(); //压栈
void pop(); //弹栈,删除最栈顶元素,使以冰月的次栈顶元素成为当前的栈顶元素 void removeObject(CCObject* pObject); //删除栈顶元素中对应内存池中的对象pObject
void addObject(CCObject* pObject); //向栈顶元素中对应内存中添加对象pObject static CCPoolManager* sharedPoolManager(); //单例类,返回单例的实例
static void purgePoolManager(); //释放单例类 //将CCAutoreleasePool类声明为CCPoolManager的友元类,使得CCPoolManager成员函数中可以直接访问CCPoolManager中的私有变量
friend class CCAutoreleasePool;
};

CCPoolManager使用了一个数组来封装成一个栈.利用栈来管理内存池.

再看CCPoolManager类的实现文件,源码如下:

//--------------------------------------------------------------------
//
// CCPoolManager
//
//--------------------------------------------------------------------
static CCPoolManager* s_pPoolManager = NULL; //全局的静态变量 //单例类
CCPoolManager* CCPoolManager::sharedPoolManager()
{
if (s_pPoolManager == NULL)
{
s_pPoolManager = new CCPoolManager();
}
return s_pPoolManager;
} //释放单例类
void CCPoolManager::purgePoolManager()
{
CC_SAFE_DELETE(s_pPoolManager);
} CCPoolManager::CCPoolManager()
{
m_pReleasePoolStack = new CCArray(); //新创建一个栈,其实就是用数组来模拟栈的行为,栈中的元素的类型为 CCAutoreleasePool*
m_pReleasePoolStack->init(); //初始化一个栈
m_pCurReleasePool = ; //将当前栈顶的元素置为NULL } CCPoolManager::~CCPoolManager()
{ finalize(); // we only release the last autorelease pool here
m_pCurReleasePool = ;
m_pReleasePoolStack->removeObjectAtIndex(); CC_SAFE_DELETE(m_pReleasePoolStack);
} //作清理栈内存的工作,栈中每个元素都是一个内存池,此函数将栈中每个内存池的内存都释放掉
void CCPoolManager::finalize()
{
if(m_pReleasePoolStack->count() > )
{
//CCAutoreleasePool* pReleasePool;
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_pReleasePoolStack, pObj)
{
if(!pObj)
break;
CCAutoreleasePool* pPool = (CCAutoreleasePool*)pObj;
pPool->clear();
}
}
} //压栈
void CCPoolManager::push()
{
CCAutoreleasePool* pPool = new CCAutoreleasePool(); //新建一个内存池,此时pPool 的引用计数为 ref = 1
m_pCurReleasePool = pPool; //并把新建的内存池赋值给栈顶,成了为栈顶元素 m_pReleasePoolStack->addObject(pPool); //把新建的内存池压入栈中,因为addObject内部作了retain的操作,此时pPool的引用计数为 ref = 2 pPool->release(); //引用计数再减1,是为了回到刚创建时的状态,此时ref = 1
} //弹栈,把当前的栈顶元素删除,把次栈顶元素变成栈顶元素
void CCPoolManager::pop()
{
//如果栈顶元素为NULL,则什么也不做,返回
if (! m_pCurReleasePool)
{
return;
} //得到栈中元素的个数
int nCount = m_pReleasePoolStack->count(); //把栈顶元素对应的内存池内存释放了
m_pCurReleasePool->clear(); //如果栈中元素的个数大于1,就是删除栈顶元素后,栈不为空
if(nCount > )
{
//把栈顶元素删除了
m_pReleasePoolStack->removeObjectAtIndex(nCount-); //把次栈顶元素赋值给当前的栈顶元素
m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - );
} } void CCPoolManager::removeObject(CCObject* pObject)
{
CCAssert(m_pCurReleasePool, "current auto release pool should not be null"); //删除栈顶元素中对应内存池中的对象pObject
m_pCurReleasePool->removeObject(pObject);
} void CCPoolManager::addObject(CCObject* pObject)
{
//把对象pObject添加到栈顶元素对应的内存池中
getCurReleasePool()->addObject(pObject);
} //得到栈顶元素对应的内存池
CCAutoreleasePool* CCPoolManager::getCurReleasePool()
{
//如果栈顶元素为NULL,也就是此栈中没有元素
if(!m_pCurReleasePool)
{
//则新建一个元素,并压入栈中,并把此元素赋值给当前栈顶元素
push();
} CCAssert(m_pCurReleasePool, "current auto release pool should not be null"); //返回栈顶元素
return m_pCurReleasePool; }

通过以上源码的分析可以看到:cocos2d-x是通过CCAutoreleasePool来保存所有需要自动释放内存的对象.而通过CCPoolManager来管理内存池的.

那么对象的释放到底是在什么时候释放的? 下篇文章介绍对象释放的时机


cocos2d-x 之 内存管理(5)的更多相关文章

  1. cocos2d内存管理

    设想如下场景, 这是一个典型的内存合理分配的场景: 在一帧内, 有若干个函数, 每个函数都会创建一系列的精灵, 每个精灵都不同, 都会占用一定的内存, 精灵的总数可能会有1000个, 而一个函数只会创 ...

  2. 【Cocos2d-x 3.x】内存管理机制与源码分析

    侯捷先生说过这么一句话 :  源码之前,了无秘密. 要了解Cocos2d-x的内存管理机制,就得阅读源码. 接触Cocos2d-x时, Cocos2d-x的最新版本已经到了3.2的时代,在学习Coco ...

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

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

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

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

  5. iOS 非ARC基本内存管理系列 -手把手教你ARC——iOS/Mac开发ARC入门和使用(转)

    手把手教你ARC——iOS/Mac开发ARC入门和使用 Revolution of Objective-c 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流 ...

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

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

  7. Cocos2D-X2.2.3学习笔记3(内存管理)

    本章节介绍例如以下: 1.C/C++内存管理机制 2.引用计数机制 3.自己主动释放机制 1.C/C++内存管理机制 相信仅仅要懂oop的都知道NEW这个keyword吧,这个通俗点说事实上就是创建对 ...

  8. cocos2dx内存管理

    cocos2dx基于引用计数管理内存,所有继承自CCObject的对象都将获得引用计数的能力,可通过调用retain成员函数用于引用计数值,调用release减少引用计数值,当计数值减为0时销毁对象. ...

  9. [置顶] 【玩转cocos2d-x之二十】从CCObject看cocos2d-x的内存管理机制

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/13765639 再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的 ...

  10. cocos2d-x游戏引擎核心之二——内存管理

    (一) cocos2d-x 内存管理 cocos2d里面管理内存采用了引用计数的方式,具体来说就是CCObject里面有个成员变量m_uReference(计数); 1, m_uReference的变 ...

随机推荐

  1. Linux scp复制文件,不需要输入密码的技巧

    当两台LINUX主机之间要互传文件时可使用SCP命令来实现,建立信任关系之后可不输入密码. 把你的本地主机用户的ssh公匙文件复制到远程主机用户的~/.ssh/authorized_keys文件中 假 ...

  2. 静态修饰符(关键字static)

    1.Static修饰的方法或变量通常称为类方法和类属性 2.静态方法中不能使用this和super关键字,也不能做为局部变量使用 3.在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成 ...

  3. ACM好书推荐

    年末感想之(渣渣的我)         仔细想想,搞比赛的日子4年有余了,确实不服老不行了,直到现在平均每天的题量都在3题左右.其实真想说,“渣渣的我”.做的题确实不少了,但是水平还是上不了档次.  ...

  4. ios 使用可视化工具charles转换pcap文件,进行流量统计(通过tcpdump抓包)

    环境准备:使用mac电脑,下载xcode,Charles 连接iPhone手机,打开xcode-window-devices-查看设备UDID 打开终端:rvictl –s 设备号 ,查看虚拟端口号 ...

  5. sql 简单事务例子

    BEGIN TRY BEGIN TRAN ) BEGIN UPDATE table SET ... END ELSE BEGIN UPDATE table SET ... UPDATE table S ...

  6. 2016-08-05:samba服务器配置

    centos samba服务器配置 配置smb.conf文件 [share] path = /home/lee writable = yes 添加smb用户 smbpasswd -a root 启动s ...

  7. NUGET命令

    主题 about_NuGet 简短说明 提供有关 NuGet 程序包管理器命令的信息. 详细说明 本主题介绍 NuGet 程序包管理器命令.NuGet 是一种集成的程序包 管理工具,用于将库和工具添加 ...

  8. webform repeater控件

    Repeater: HeaderTemplate - 在加载开始执行一遍 ItemTemplate - 有多少条数据,执行多少遍 FooterTemplate - 在加载最后执行一遍 Alternat ...

  9. ASP.NET Web API系列教程目录

    ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Start ...

  10. zk源码环境搭建

    zk不是使用maven管理的. 将zk的src下的代码导入eclipse,lib下的jar包导入工程. QuorumPeerMain类的main方法是入口,启动了zk的server,参数是conf文件 ...