1. 总结

Sprite和SpriteFrame和Texture2D关系紧密,三个类都继承了Ref类。精灵有成员精灵帧和纹理,精灵帧有成员纹理。精灵帧和纹理被精灵帧引用时,引用计数增加,不再被引用时,引用计数减少。纹理被精灵帧引用时也同理。

一个纹理可以被多个精灵帧、精灵引用,一个精灵帧可以被多个精灵引用。

为什么纹理缓存容器不用CC的包装类Map

纹理缓存和精灵帧缓存不同,纹理缓存的容器不是包装类,即向容器中增加和删除纹理不会改变纹理的引用计数。

纹理除异步之外不执行autorelease(),精灵和精灵帧在create()执行autorelease()。

纹理不使用autorelease(),确保了不被引用的纹理不会在每帧结束后被自动release(),而是在需要释放的时候调用remove等方法手动执行release(),确保对内存中的纹理手动释放。也是让暂时没用但以后要用的纹理留在内存中,避免以后重新新建该texture。

纹理缓存的addImage方法中,将新纹理加入到容器时,不会增加引用计数。因为在精灵的create方法中,addImage方法执行后执行setTexture方法,使得引用计数加1。

2. Sprite

Sprite成员变量包括:

Texture2D*       _texture;              /// Texture2D object that is used to render the sprite
SpriteFrame* _spriteFrame;

create(...)

我们执行Sprite类的createxxx(...)等方法,都会新建Sprite对象,对成员变量_texture和_spriteFrame等设置默认值,再调用autorelease()方法,将Sprite对象交给内存管理池自动管理。

setTexture(Texture2D *texture)

在给精灵设置纹理时,若纹理指针为空指针,则执行以下方法尝试从纹理缓存中获取Key为CC_2x2_WHITE_IMAGE_KEY的纹理的指针:

_director->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY);

若空白纹理不存在于纹理内存,则新建Image类对象从而新建空白纹理。Image对象继承Ref类,新建时默认引用计数=1,在空白纹理的指针赋给纹理指针后,Image对象执行release()方法,从内存中删除。

此时,若参数纹理指针不等于Sprite本身的纹理指针时,参数纹理retain(),本身纹理release(),参数纹理作为本身纹理指针。

setSpriteFrame(SpriteFrame *spriteFrame)

在给精灵设置精灵帧时,若参数精灵帧指针不等于本身精灵帧指针,对本身精灵帧release(),参数精灵帧retain(),参数精灵帧作为本身精灵帧。

~Sprite()

Sprite对象析构时,会对成员_spriteFrame和_texture执行release()。

addChild(...) removeChild(...) 不再赘述。

3. SpriteFrame SpriteFrameCache

精灵帧缓存的容器_spriteFrames是Map<std::string, SpriteFrame*>类型,添加精灵帧和删除都封装了retain()和release()方法

SpriteFrame::create(const std::string& filename, const Rect& rect)

创建精灵帧时,要将精灵帧执行autorelease()方法,放入内存管理池。

~SpriteFrame()

析构时,对精灵帧成员_texture执行release()

SpriteFrame::setTexture(Texture2D * texture)

对精灵帧的成员_texture设置新的时,原先纹理执行release(),新纹理执行retain()。

SpriteFrame::initWithTexture(Texture2D* texture, ...)

用纹理对精灵帧初始化,纹理执行retain()

SpriteFrameCache::removeSpriteFrames()

SpriteFrameCache::removeSpriteFrameByName(const std::string& name)

SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D* texture)

删除是对Map容器执行clear(),会对容器中所有精灵帧执行release(),再清空map。删除特定精灵帧,对容器中精灵帧release()。增加特定精灵帧,对容器中精灵帧retain()。

SpriteFrameCache::destroyInstance()

精灵帧缓存是单例,销毁时执行release()。

4. Texture2D TextureCache

纹理缓存是对纹理的缓存,纹理指针以map形式被保存在容器_textures中,容器类型std::unordered_map<std::string, Texture2D*>。

在用Image对象创建纹理时,新建的Image对象使用完后要调用release()及时从内存中删除。

~TextureCache()

析构时对容器中所有纹理执行release()。

addImage(const std::string &path)

在添加纹理到纹理缓存中,如果纹理不存在于缓存,且又新建该纹理失败,就把刚刚new的texture对象release()。

image = new (std::nothrow) Image();
texture = new (std::nothrow) Texture2D();
if (texture && texture->initWithImage(image))
{
// ...
}
else
{
// ...
CC_SAFE_RELEASE(texture);
texture = nullptr;
}
CC_SAFE_RELEASE(image);

removeAllTextures()

删除缓存容器中所有纹理,实际上是对这些纹理执行release()。

removeUnusedTextures()

删除没有使用的纹理,实际是对引用计数为1的纹理-1。

removeTexture(Texture2D* texture) removeTextureForKey(...)

it->second->release();
it = _textures.erase(it);

Cocos2d-x 学习笔记(7) 内存管理 Sprite SpriteFrame Texture2D的更多相关文章

  1. linux kernel学习笔记-5内存管理_转

    void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...

  2. XV6学习笔记(2) :内存管理

    XV6学习笔记(2) :内存管理 在学习笔记1中,完成了对于pc启动和加载的过程.目前已经可以开始在c语言代码中运行了,而当前已经开启了分页模式,不过是两个4mb的大的内存页,而没有开启小的内存页.接 ...

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

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

  4. COCOS学习笔记--Cocod2dx内存管理(三)-Coco2d-x内存执行原理

    通过上两篇博客.我们对Cocos引用计数和Ref类.PoolManager类以及AutoreleasePool类已有所了解,那么接下来就通过举栗子来进一步看看Coco2d-x内存执行原理是如何的. / ...

  5. 嵌入式linux学习笔记1—内存管理MMU之虚拟地址到物理地址的转化

    一.内存管理基本知识 1.S3C2440最多会用到两级页表:以段的方式进行转换时只用到一级页表,以页的方式进行转换时用到两级页表.页的大小有三种:大页(64KB),小页(4KB),极小页(1KB).条 ...

  6. Linux内核学习笔记——内核内存管理方式

    一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...

  7. ios学习笔记之内存管理

    一,内存管理类型定义      1,基本类型  任何C的类型,eg:      int,short,char,long,long long,struct,enum,union等属于基本类型或结构体   ...

  8. arm-linux学习笔记3-linux内存管理与文件操作

    配置好linux系统之后需要vim配置一下,有助于我们的编程,主要的配置如下 在/etc/vim/vimrc文件中 "显示行号 set number "自动缩进 set autoi ...

  9. 《C#高级编程》学习笔记----c#内存管理--栈VS堆

    本文转载自Netprawn,原文英文版地址 尽管在.net framework中我们不太需要关注内存管理和垃圾回收这方面的问题,但是出于提高我们应用程序性能的目的,在我们的脑子里还是需要有这方面的意识 ...

随机推荐

  1. 控制执行流程之break和continue

    1.在任何迭代语句的主体部分,都可以用break和continue来控制程序执行流程. 2.注意: break:用于强行退出循环, 不执行循环中剩余的语句:continue:停止当前的循环,执行下一次 ...

  2. linux文件系统分区、格式化、挂载、卷标挂载、永久挂载

    思想不放松你的行为就不会放松,你的行为放松了,说明你的思想放松了.

  3. Spring boot 自定义banner的在线制作

    目前工作不是很忙,利用闲暇的时间,在给自己不断地充电,提升自己的技术实力. 目前在做一个基于Spring Boot2.x+webmagic+quartz的爬虫项目[hotDog]https://git ...

  4. jenkins自动化部署项目8 -- 新建job(服务代码部署在linux上)

    jenkins(windows) ----> 应用服务器(linux): 1.后台java服务: 与部署在windows上不同的是,这里我选择了在[构建后操作]中使用ssh向远程linux服务器 ...

  5. Flume系列一之架构介绍和安装

    Flume架构介绍和安装 写在前面 在学习一门新的技术之前,我们得知道了解这个东西有什么用?我们可以使用它来做些什么呢?简单来说,flume是大数据日志分析中不能缺少的一个组件,既可以使用在流处理中, ...

  6. SpringBootSecurity学习(12)前后端分离版之简单登录

    前后端分离 前面讨论了springboot下security很多常用的功能,其它的功能建议参考官方文档学习.网页版登录的形式现在已经不是最流行的了,最流行的是前后端分离的登录方式,前端单独成为一个项目 ...

  7. 3.form表单

    1.Form标签:用来将表单外的内容与表单进行关联.其主要元素有input,button,select. action属性:指定表单的发送地址. Novalidate属性:数据提交时不校验. Targ ...

  8. Idea 设置Eclipse快捷键(常用)

    使用Idea不习惯,特此将其配置成Eclipse风格的. 1.选择Eclipse风格,选择copy一份,可以自己重命名. 2.设置生成快捷键的快捷键(例如:Eclipse中的Alt+/) 3.设置ma ...

  9. Navicat 设置自增长初始值

    设置主键自增初始值

  10. 节点操作--JavaScript

    1 - 概念 网页中的所有内容都是节点(标签.属性.文本.注释),在DOM中,节点使用node来表示. HTML DOM树中的所有节点均可通过JS进行访问,所有HTML元素(节点)均可被修改,也可以创 ...