cocos2dx 内存管理

cocos2dx的内存管理移植自Objective-C, 对于没有接触过OC的C++开发人员来说是挺迷惑的。不深入理解内存管理是无法写出好的C++程序的,我用OC和cocos2dx也有一段时间了,在此总结一下,希望对想用cocos2dx开发游戏的朋友有所帮助。

C++的动态内存管理一般建议遵循谁申请谁释放的原则,即谁通过new操作符创建了对象,谁就负责通过delete来释放对象。如果对象的生命周期在一个函数内,这很容易做到,在函数返回前delete就行了。但一般我们在函数中new出来的对象的生命周期都会超出该函数体(例如作为函数的返回值),否则我们可以直接在栈上创建对象,不需要使用动态内存,也省去了内存管理的麻烦(当然大对象是不适合在栈上分配的)。如果对象的生命周期超出了创建对象的函数,我们就很难再遵循谁申请谁释放的原则了,我们必须在函数外的某个合适的地方释放对象,如果这个对象同时被多个对象引用,问题就很复杂了,必须保证所有该对象的引用者都不再需要它了才可以释放,在实际使用中这点是很难保证的。于是,各种内存管理技术应运而生了:垃圾回收器,智能指针,引用计数...... cocos2dx移植于Objective-C,因此和OC一样使用了比较原始的引用计数的方法来管理内存。

cocos2dx通过CCObject和CCPoolManager来实现内存管理。所有使用cocos2dx引用计数机制的类都必须派生自CCObject。CCObject有一个计数器成员变量m_uReference,当CCObject被构造时m_uReference=1,表示该对象被引用1次。CCObject的retain方法可以使计数器加1,release方法可以使计数器减1。当计数器减到0时release方法会通过delete this来销毁自己。

手动内存管理
使用retain和release,我们可以手动管理内存, 通过new 创建的对象,使用release来释放。
CCObject *obj=new CCObject();

obj->release();
和new\delete需配对使用一样,new\release也要配对使用才可确保内存被释放。有人会说这个把delete换成release有意义吗?需要注意的是这个的release并不等同于delete,release只是表示引用计数减1,并不是真正销毁obj所占用的内存。只有当obj的引用计数为0时内存才会被销毁。下面的代码就展示了release和delete不同:
CCArray *array = CCArray::array();
CCObject *obj = new CCObject();// m_uReference=1
array->addObject(obj); // CCArray的addObject方法会自动调用obj的retain方法,使引用计数加1,表示拥有obj,此时m_uReference=2
obj->release(); // 这里的release和new配对,obj引用计数减1,但是并不会释放obj, 此时m_uReference=1;
obj->doSomething(); // 在release之后我们依然可以正常使用obj,它并没有被释放
array->removeObject(obj); //当我们把obj从CCArray中移除时,CCArray会自动调用obj的release,此时m_uReference=0, obj被销毁
obj->doSomething(); // 错误,obj已经被销毁
对于手动内存管理,我们需遵循new/release,retain/release配对使用的原则,谁new,谁release;谁retain,谁release。new出来的对象如果是要加入到cocos2dx集合中,添加完后一定不要忘记release,集合类已经为你retain了对象,你还是要为你的new配对release一次,否则当这个对象从集合中移除时不会被正确销毁。

自动内存管理
手动内存管理似乎比new/delete更麻烦,而且并没有解决一开始我们提到的函数内创建的对象的生命周期超出函数怎么办的问题。new和release需配对使用,那在函数内创建的对象返回前我们需要调用一次release,在这之前如果我们没有把对象加入到什么集合中,对象就被销毁了,和使用new/delete是一样的。自动内存管理就可以解决这个问题。CCObject有一个autorelease方法,如果一个对象在用new关键字创建之后调用了autorelease,我们就不必关心它的释放问题。CCPoolManager会在游戏的每一帧结束后自动释放这些autorelease的对象。CCPoolManager其实依然是通过引用计数来管理对象生命周期的,它里面有一个CCAutoreleasePool,我们调用CCObject的autorelease就是把自己加入到CCAutoreleasePool的对象数组里面。当每一帧结束的时候,CCPoolManager会将对象从数组中移除,如果这时候对象的引用计数为0,对象就自然被释放了。对于用new关键字创建之后调用了autorelease的对象,不需要再release一次。

cocos2dx中的大部分对象都可以通过静态工厂方法来创建出这种会自动释放的对象,这是cocos2dx的一条规则,我们自己实现的类最好也遵循这样的规则,以免引起其他开发人员误会。如果一个对象是通过类的静态方法创建而不是new出来的,我们就不需要release它。

其实这里的自动并没有我们想得那么好,对于像C#,Java这种托管语言,虚拟机为你完成了所有内存管理工作,程序员完全从内存分配和释放中解脱了出来。cocos2dx的autorelease只不过每帧结束后自动在为我们释放了一次对象,如果我们希望创建的对象在下一帧仍然可以使用,我们需要显式地retain一下这个对象或者把对象加入到集合中(集合会帮我们retain一次)。既然retain了,我们还是不能忘记在适当的地方release。比较常见的用法是创建一个autorelease对象作为类成员变量,我们在通过静态方法得到实例的指针后除了赋值给类成员,还要retain一次,然后在类的析构函数中release一次。如果没有retain,以后使用该成员的时候就会因为对象被销毁而发生内存访问错误,这是新手很容易遇到的陷阱。

时间: 2017-10-09

cocos2dx 内存管理的相关文章

Cocos2d-x的内存管理总结_Android

Cocos2d-x引擎的核心是用C++编写的,那对于所有使用该引擎的游戏开发人员来说,内存管理是一道绕不过去的坎. 关于Cocos2d-x内存管理,网上已经有了许多参考资料,有些资料写的颇为详实,因为在内存管理这块我不想多费笔墨,只是更多的将思路描述清楚. 一.对象内存引用计数 Cocos2d-x内存管理的基本原理就是对象内存引用计数,Cocos2d-x将内存引用计数的实现放在了顶层父类CCObject中,这里将涉及引用计数的CCObject的成员和方法摘录出来: 复制代码 代码如下: clas

Cocos2d-x的内存管理总结

Cocos2d-x引擎的核心是用C++编写的,那对于所有使用该引擎的游戏开发人员来说,内存管理是一道绕不过去的坎. 关于Cocos2d-x内存管理,网上已经有了许多参考资料,有些资料写的颇为详实,因为在内存管理这块我不想多费笔墨,只是更多的将思路描述清楚. 一.对象内存引用计数 Cocos2d-x内存管理的基本原理就是对象内存引用计数,Cocos2d-x将内存引用计数的实现放在了顶层父类CCObject中,这里将涉及引用计数的CCObject的成员和方法摘录出来:复制代码 代码如下:class

1.cocos2dx内存管理和CCArray,CCMenuItem

1 C++内存管理 A 栈上的空间 自生自灭,不用管理 B 堆上的空间 手动new,手动delete,否则产生内存泄漏 2 内存管理的难处 管理原则,谁申请谁释放 3 内存的智能管理 主要有两种实现智能管理内存的技术,一种是引用计数,一是垃圾回收. 引用计数:通过给每个对象维护一个引用计数器,记录该对象当前被引用的次数.当对象增加一次引用时,计数器加1:而对象失去一次引用时,计数器减1:当引用计数为0 时,标志着该对象的生命周期结束,自动触发对象的回收释放.引用计数解决了对象的生命周期管理问题,

Cocos2d-x开发中C++内存管理

由于开始并没有介绍C++语言C++的内存管理当然也没进行任何的说明为了掌握Cocos2d-x中的内存管理机制是有必要先了解一些C++内存管理的知识.C++内存管理非常复杂如果完全地系统地介绍可能需要一本书的篇幅才能解释清楚.这里只给大家介绍C++内存管理最为基本的用法. 内存分配区域创建对象需要两个步骤第一步为对象分配内存第二步调用构造函数初始化内存.在第一步中对象分配内存时候我们可以选择几个不同的分配区域这几个区域如下栈区域分配.栈内存分配运算内置于处理器的指令集中效率很高但是分配的内存容量有

从CCObject看cocos2d-x的内存管理机制

再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的属性和方法后,CCObject还剩下什么? 1.剩下什么? 可以看到整个CCObject就是围绕着m_uReference和m_uAutoReleaseCount在转.这两个变量的解释如下.所以CCObject剩下的其实就是对内存的管理. [cpp] view plaincopy CCObject::CCObject(void)//构造函数   : m_nLuaID(0)   , m_uReference(1) //引用计数,初始为1

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

  Cocos2d-x与ios内存管理分析(在游戏中减少内存压力) 猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网--Cocos2Dev.com,谢谢!  原文地址: http://www.cocos2dev.com/?p=281 注:自己以前也写过Cocos2d-x如何优化内存的使用,以及内存不足的情况下怎么处理游戏.今天在微博中看到有朋友介绍了下内存,挺详细的.不知道是谁写的,我记录下. 一,iOS与图片内存 在iOS上,图片会被自动缩放到2的N次方大小.比如一张1024*10

Cocos2d-x开发中Ref内存管理

Ref类是Cocos2d-x根类Cocos2d-x中的很多类都派生自它例如我们熟悉的节点类Node也派生自Ref.我们介绍Ref内存管理.内存引用计数Ref类设计来源于Cocos2d-iphone的CCObject类在Cocos2d-x 2.x中也叫CCObject类.因此Ref类的内存管理是参考Objective-C手动管理引用计数Reference Count而设计的.如图所示是内存引用计数原理示意图.  每个Ref对象都有一个内部计数器这个计数器跟踪对象的引用次数被称为"引用计数"

cocos2d x-cocos2dx-cpp中的内存管理问题

问题描述 cocos2dx-cpp中的内存管理问题 请教一下:在GitHub中的cocos2dx-cpp中的cocos2d-x / tests / cpp-tests / Classes / AccelerometerTest / AccelerometerTest.cpp的代码`AccelerometerTestScene::runThisTest(){auto layer = new AccelerometerTest();addChild(layer);layer->release();/

JSB内存管理

原文地址:http://www.cocos2d-x.org/wiki/Memory_Management_of_JSB by u0u0 翻译:晋文格墨 JSB的内存管理 基于Cocos2d-x 2.15,但同样适用于Cocos2d-x 3.0. JSB对象的生命周期 总所周知,javascript有自己的内存管理机制,即垃圾回收.Cocos2d-x模拟垃圾回收系统来管理Cocos对象.但这里有一个问题,就是将Cocos2d-x对象绑定到javascript对象时由谁负责内存管理. 先看一个案例.