cocos中所有的对象都是继承自Ref基类,Ref的职责就是对对象进行引用计数管理

内存管理中最重要的是三个方法retain()、release()、autorelease()

在cocos中创建对象的标准流程是:

创建对象->初始化->添加到自动内存管理->返回创建成功的对象

就比如下面这段代码1:创建Node对象

//代码1
Node * Node::create()
{
Node * ret = new (std::nothrow) Node();
if (ret && ret->init())
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}

在代码1中,我们只需要调用create方法就可以实现创建对象、初始化和自动管理内存。

在cocos中有的函数中直接使用了create的宏定义,调用对象的create方法就可以执行代码2,实现的功能和代码1是一样的。

//代码2
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = nullptr; \
return nullptr; \
} \
}

代码2中调用autorelease方法,将对象加入自动内存管理池自动管理。

代码3是autorelease方法的实现

//代码3
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}

首先看一下代码4,PoolManager的getInstance方法

在代码4中创建了PoolManager对象并调用了this的AutoreleasePool方法(代码5)

"cocos2d autorelease pool"是这个自动管理池的name

//代码4
PoolManager* PoolManager::getInstance()
{
if (s_singleInstance == nullptr)
{
s_singleInstance = new (std::nothrow) PoolManager();
// Add the first auto release pool
new AutoreleasePool("cocos2d autorelease pool");
}
return s_singleInstance;
}

在代码5中可以看到先是对_managedObjectArray预留空间,然后将this加了进去

//代码5
AutoreleasePool::AutoreleasePool(const std::string &name)
: _name(name)
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
, _isClearing(false)
#endif
{
_managedObjectArray.reserve(150);
PoolManager::getInstance()->push(this);
}

在代码3中还调用了getCurrentPool方法用来获取当前的内存管理池

//代码6
AutoreleasePool* PoolManager::getCurrentPool() const
{
return _releasePoolStack.back();
}

然后把this加入到当前的内存管理池中作为一个ref对象进行管理,如代码7

//代码7
void AutoreleasePool::addObject(Ref* object)
{
_managedObjectArray.push_back(object);
}

整个流程如下图所示

自动内存管理的结构如下图,用一个栈来存储多个自动内存管理池,在自动内存管理池中又有若干个ref对象。

在内存管理中主要是靠引用计数来记录对象的使用情况,当一个对象被create时会给它分配内存,并且会调用retain()方法让引用计数+1;当调用release()时会让引用计数-1,release时会检查引用计数是否为0,引用计数为0时会调用delete删除对象并释放内存。

在每一帧结束时会清理当前的内存管理池,将每一个ref对象的引用计数都-1,这帧结束之后,内存管理池中就没有这个ref对象了,引用计数是ref自己的属性,当下一次被release时如果引用计数=0,就会被释放。

void Director::mainLoop()
{
......
PoolManager::getInstance()->getCurrentPool()->clear();
}
}
void AutoreleasePool::clear()
{
std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);
for (const auto &obj : releasings)
{
obj->release();
}
}

retain()和release()只是帮助我们记录一个对象的引用次数,在程序中几乎不用手动调用。

从零开始のcocos2dx生活(一)内存管理的更多相关文章

  1. Cocos2d-x 3.1 内存管理机制

    Cocos2d-x使用的内存管理方式是引用计数.引用计数是一种非常有效的机制.通过给每个对象维护一个引用计数器,记录该对象当前被引用的次数.当对象添加一次引用时,计数器加1:而对象失去一次引用时.计数 ...

  2. cocos2dx中的内存管理机制及引用计数

    1.内存管理的两大策略: 谁申请,谁释放原则(类似于,谁污染了内存,最后由谁来清理内存)--------->适用于过程性函数 引用计数原则(创建时,引用数为1,每引用一次,计数加1,调用结束时, ...

  3. 菜鸟学习Cocos2d-x 3.x——内存管理

    菜鸟学习Cocos2d-x 3.x——内存管理 2014-12-10 分类:Cocos2d-x / 游戏开发 阅读(394) 评论(6)    亘古不变的东西 到现在,内存已经非常便宜,但是也不是可以 ...

  4. cocos2dx中的内存管理方式

    转载:http://www.cocoachina.com/bbs/read.php?tid=195219 今天看了一下cocos2dx的内存管理机制,有些地方不太好理解搞了挺长的时间,现在感觉自己理解 ...

  5. cocos2d-x 3.0 内存管理机制

    ***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...

  6. 【转】cocos2d-x与ios内存管理分析(在游戏中减少内存压力)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=281 注:自己以前也写过coco ...

  7. cocos2d-x与ios内存管理分析(在游戏中减少内存压力)

    转自:http://www.cocos2dev.com/?p=281 注:自己以前也写过cocos2d-x如何优化内存的使用,以及内存不足的情况下怎么处理游戏.今天在微博中看到有朋友介绍了下内存,挺详 ...

  8. cocos2d-x与ISO内存管理(转)

    一,IOS与图片内存 在IOS上,图片会被自动缩放到2的N次方大小.比如一张1024*1025的图片,占用的内存与一张1024*2048的图片是一致的.图片占用内存大小的计算的公式是:长*宽*4.这样 ...

  9. 从零开始のcocos2dx生活(二)Node

    节点 Node 文章目录 节点 Node 前言 变量初始化 创建一个节点对象 获取节点依赖的计数器 获取节点的描述(获取节点的Tag) 节点的局部层顺序值(LocalZOrder) 设置节点的Loca ...

随机推荐

  1. oracle函数 RAWTOHEX(c1)

    [功能]将一个二进制构成的字符串转换为十六进制 [参数]c1,二进制的字符串 [返回]字符串 [示例] select RAWTOHEX('A123')  from dual;

  2. include 语句中使用双引号与括号有什么区别?

    Include 的语法 你在学习如何构造函数时,看到了不同的 include 语句: # include <iostream> # include "distance.h&quo ...

  3. shell awk杂项

    awk '{ ;++i<=NF;){ a[i]=a[i]?a[i]",'\''"$i"'\''":"'\''"$i"'\'' ...

  4. Bert系列(三)——源码解读之Pre-train

    https://www.jianshu.com/p/22e462f01d8c pre-train是迁移学习的基础,虽然Google已经发布了各种预训练好的模型,而且因为资源消耗巨大,自己再预训练也不现 ...

  5. Fiddler快速入门

    Fiddler是一个免费.强大.跨平台的HTTP抓包工具.Wireshark也是一个强大的抓包工具,不过Wireshark是一个通用的抓包工具,主要精力放在各种协议上了,针对HTTP的特定功能较少.所 ...

  6. WebStorm使用参考手册

    WebStorm 是 JetBrains 推出的一款商业的 JavaScript 开发工具 任何一个编辑器都需要保存(ctrl + s),这是所有win平台上编辑类软件的特点,但是webstorm编辑 ...

  7. 解决margin塌陷和margin合并

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. theadClasses设置Bootstrap Table表头样式

    通过theadClasses属性设置表头样式. thead-light设置灰色背景 //bootstrap table初始化数据 itxst.com $('#table').bootstrapTabl ...

  9. 软件自动化测试 selenium IDE + Firebug + python脚本

    按顺序步骤来 一.安装软件   1.1.1 webDriver(就是selenium IDE) 解析:本来这两个东西就合成一个了,但是更新到后来,安装的时候又独立安装的.    安装  Python  ...

  10. JPA进行insert操作时会首先select吗

    在某个项目中,使用JPA的saveAll方法去批量写入数据时,通过打印sql,发现每次insert前都会先select一次,极大的浪费了写入性能. 分析一下代码,saveAll() @Transact ...