设想如下场景,

这是一个典型的内存合理分配的场景:

在一帧内,

有若干个函数,

每个函数都会创建一系列的精灵,

每个精灵都不同,

都会占用一定的内存,

精灵的总数可能会有1000个,

而一个函数只会创建10个精灵这样,

创建的精灵只会在这个函数中使用,

大致代码如下:

  1. for(int i = 0; i < 10; i++)
  2. {
  3. Sprite* s = Sprite::create();
  4. //-- doSomething --
  5. }

这样做会造成内存泄露吗?

答案是当然不会,

但是这样会造成一帧内的内存峰值过高,

因为在引擎的自动内存管理中,

所有的释放内存操作都是在每一帧的结束才会进行的,

所以就算申请的内存在这一帧中不会有其他地方会使用,

它的内存也不会随着作用域的结束而释放的。

那么我们应该如何优化这段代码呢?如下

 
  1. AutoreleasePool pool;  
  2. for (int i = 0; i < 10; i++)
  3. {
  4. Sprite* s = Sprite::create();
  5. //-- doSomething --
  6. }

只需要在函数的第一句加上 AutoreleasePool pool;

就可以实现在函数结束的时候自动将create的指针释放了,

那么为什么会有那么神奇的效果呢?

我们来分析一下这个函数的构造函数以及析构函数,

首先分析一下构造函数:

  1. AutoreleasePool::AutoreleasePool()
  2. : _name("")
  3. {
  4. _managedObjectArray.reserve(150);
  5. PoolManager::getInstance()->push(this);
  6. }

他向PoolManager的单例中push了自己,

我们进入push中看看它的具体实现

void PoolManager::push(AutoreleasePool *pool)
{
_releasePoolStack.push_back(pool);
}

直接向_releasePoolStack栈中压入了this,

那这个将会起到什么效果呢?

这就不得不说一下autorelease的实现了,

众所周知,

create函数的内存自动管理机制依赖于autorelease函数,

那么autorelease函数是干嘛用的呢:

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

向某个Pool池添加对象,

那么getCurrentPool获取的是那个内存管理池呢?

AutoreleasePool* PoolManager::getCurrentPool() const
{
return _releasePoolStack.back();
}

就是最后我们通过push添加进来的那个池子,

所以每创建一个AutoreleasePool 对象,

都会压入PoolManager中。

然后后续的autorelease操作是将对象加入到最新创建的AutoreleasePool 对象中。

那么最终要通过什么途径让函数在函数结束的时候自动释放内存呢?我们知道,作用域结束的时候,会调用普通对象的析构函数,那么就来看看AutoreleasePool 的析构函数执行了什么吧

AutoreleasePool::~AutoreleasePool()
{
clear();
PoolManager::getInstance()->pop();
}

第一个是clear函数,

这是一个非常关键的函数,

我们跟踪进去

void AutoreleasePool::clear()
{
for (const auto &obj : _managedObjectArray)
{
obj->release();
}
_managedObjectArray.clear();
}

它会将所有addObject的对象全部执行一次release操作。

这样就可以实现在函数结束的时候自动释放内存了。

PoolManager::getInstance()->pop();

一行代码主要是从PoolManager中将当前AutoreleasePool 对象弹出栈(因为当前对象已经析构了)

上述就是通过使用AutoreleasePool 来合理的管理内存了

cocos2d内存管理的更多相关文章

  1. cocos2d内存管理,类的生命周期

    下面资料来自<Cocos2d-x之Lua核心编程>

  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脚本相关的 ...

随机推荐

  1. HTML CSS + DIV实现整体布局

    HTML CSS + DIV实现整体布局 1.技术目标: 开发符合W3C标准的Web页面 理解盒子模型 实现DIV+CSS整体布局 2.什么是W3C标准? W3C:World Wide Web Con ...

  2. Java 运行环境的安装、配置与运行

    (一)SDK 的下载与安装 1. 下载SDK 为了建立基于SDK 的Java 运行环境,需要先下载Sun 的免费SDK 软件包.SDK 包含了一整套开发工具,其中包含对编程最有用的是Java 编译器. ...

  3. vim的使用

    vim的定位 home:光标移到行首 end:光标移到行尾 pageup:屏幕上翻页 pagedow:屏幕下翻页 shift+g:定位行  如转至10行   10shift+g shift+gg 转至 ...

  4. FCC上的初级算法题

    核心提示:FCC的算法题一共16道.跟之前简单到令人发指的基础题目相比,难度是上了一个台阶.主要涉及初步的字符串,数组等运算.仍然属于基础的基础,官方网站给出的建议完成时间为50小时,超出了之前所有非 ...

  5. ctypes 操作 python 与 c++ dll 互传结构体指针

    CMakeLists.txt # project(工程名) project(blog-3123958139-1) # add_library(链接库名称 SHARED 链接库代码) add_libra ...

  6. MONO加载DLL调试命令

    http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/ http://www.mono-project.com/ ...

  7. CKEditor的使用方法

    CKEditor的使用方法 2014-03-31 09:44 8649人阅读 评论(1) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. ckeditor 的官方网站是 http:/ ...

  8. OC-SEL

    SEL SEL对应方法的地址 _cmd代表当前方法 1.  方法的存储位置 每个类的方法列表都存储在类对象中 每个方法都有一个与之对应的SEL类型的对象 根据一个SEL对象就可以找到方法的地址,进而调 ...

  9. Hibernate SQL优化技巧dynamic-insert="true" dynamic-update="true"

    最近正在拜读Hibernate之父大作<Java Persistence with Hibernate>,颇有收获.在我们熟悉的Hibernate映射文件中也大有乾坤,很多值得我注意的地方 ...

  10. Nosql 之 Redis(可做缓存 )

    下载 可以下载解压安装的 地址:https://github.com/dmajkic/redis/downloads 修改 redis.conf 取消注释 requirepass foobared运行 ...