cocos2dx 之内存管理
- CCObject *obj=new CCObject();
- ...
- obj->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已经被销毁
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一次,否则当这个对象从集合中移除时不会被正确销毁。
cocos2dx 采用引用计数管理自己的内存:
引用计数:
引用计数就是通过给每个对象维护一个引用计数器,记录该对象当前被引用的次数。当对象增加一次引用时,计数器+1.而对象失去一次引用时,计数器-1,当引用计数器为0时。标志着该对象的生命周期结束,自动触发对象的回收释放。 为了实现引用计数器,cocos2dx实现了自己的根类ccobject。引 擎中所有类都派生自ccobject类。一下ccobject的定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
class CC_DLL Object
{
public :
/// object id, ScriptSupport need public _ID
unsigned int _ID;
/// Lua reference id
int _luaID;
protected :
/// count of references
unsigned int _reference;
/// count of autorelease
unsigned int _autoReleaseCount;
public :
/**
* Constructor
*
* The object's reference count is 1 after construction.
* @js NA
*/
Object();
/**
* @js NA
* @lua NA
*/
virtual ~Object();
/**
* Release the ownership immediately.
*
* This decrements the object's reference count.
*
* If the reference count reaches 0 after the descrement, this object is
* destructed.
*
* @see retain, autorelease
* @js NA
*/
inline void release()
{
CCASSERT(_reference > 0 , "reference count should greater than 0" );
--_reference;
if (_reference == 0 )
delete this ;
}
/**
* Retains the ownership.
*
* This increases the object's reference count.
*
* @see release, autorelease
* @js NA
*/
inline void retain()
{
CCASSERT(_reference > 0 , "reference count should greater than 0" );
++_reference;
}
/**
* Release the ownership sometime soon automatically.
*
* This descrements the object's reference count at the end of current
* autorelease pool block.
*
* If the reference count reaches 0 after the descrement, this object is
* destructed.
*
* @returns The object itself.
*
* @see AutoreleasePool, retain, release
* @js NA
* @lua NA
*/
Object* autorelease();
/**
* Returns a boolean value that indicates whether there is only one
* reference to the object. That is, whether the reference count is 1.
*
* @returns Whether the object's reference count is 1.
* @js NA
*/
bool isSingleReference() const ;
/**
* Returns the object's current reference count.
*
* @returns The object's reference count.
* @js NA
*/
unsigned int retainCount() const ;
/**
* Returns a boolean value that indicates whether this object and a given
* object are equal.
*
* @param object The object to be compared to this object.
*
* @returns True if this object and @p object are equal, otherwise false.
* @js NA
* @lua NA
*/
virtual bool isEqual( const Object* object);
/**
* @js NA
* @lua NA
*/
virtual void acceptVisitor(DataVisitor &visitor);
/**
* @js NA
* @lua NA
*/
virtual void update( float dt) {CC_UNUSED_PARAM(dt);};
friend class AutoreleasePool;
};
|
通过以上代码我们可以看出cocos2dx的内存管理机制和objective-c的管理一样。都是当_reference = 0时释放内存。_autoReleaseCount自动释放池的引用计数
1
2
3
4
5
6
7
8
9
|
auto sprite1 = new Sprite();
sprite1->initWithSpriteFrameName( "btn_adventure_normal_CN.png" ); //引用计数器+1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->retain(); //引用计数器+1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->release(); //引用计数器-1
CCLOG( "retaincount = %d" ,sprite1->retainCount());
sprite1->autorelease(); //只是把该sprite放入自动释放池中。引用计数器不变。等待管理器自动释放
CCLOG( "retaincount = %d" ,sprite1->retainCount());
|
coco2dx 内存管理原则
1.程序段必须成对执行retain()和release()或者执行autorelease()来开始和结束对对象的引用 2.工厂方法返回前,应通过autorelease()结束对该对象的引用 3.对象传值时,应考虑到新旧对象相同的特殊情况 4.尽量使用release()而不是autorelease()来释放对象,以确保性能。 5.保存ccobject的子类对象时,应严格使用cocos2dx提供的容器。
内存管理涉及到的宏:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#define CC_SYNTHESIZE_RETAIN(varType, varName, funName) \
private : varType varName; \
public : virtual varType get##funName( void ) const { return varName; } \
public : virtual void set##funName(varType var) \
{ \
if (varName != var) \
{ \
CC_SAFE_RETAIN(var); \
CC_SAFE_RELEASE(varName); \
varName = var; \
} \
}
#define CC_SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while ( 0 )
#define CC_SAFE_DELETE_ARRAY(p) do { if (p) { delete[] (p); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_FREE(p) do { if (p) { free(p); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_RELEASE(p) do { if (p) { (p)->release(); } } while ( 0 )
#define CC_SAFE_RELEASE_NULL(p) do { if (p) { (p)->release(); (p) = nullptr; } } while ( 0 )
#define CC_SAFE_RETAIN(p) do { if (p) { (p)->retain(); } } while ( 0 )
|
cocos2dx 之内存管理相关推荐
- Cocos2Dx之内存管理-欧阳左至
Cocos2Dx的所有的类都直接或间接继承自CCObject,让类具有自动的内存管理能力.根本上讲,是借鉴自苹果的设计思维.从iPhone版的Cocos2Dx,到C++版的Cocos2Dx,以及到后面 ...
- cocos2dx多线程以及线程同步 与 cocos2dx内存管理与多线程问题
cocos2d-x引擎在内部实现了一个庞大的主循环,每帧之间更新界面,如果耗时的操作放到了主线程中,游戏的界面就会卡,这是不能容忍的,游戏最基本的条件就是流畅性,这就是为什么游戏开发选择C++的原因. ...
- Cocos2d-X内存管理研究一
http://hi.baidu.com/tzkt623/item/651ca7d7a0aff6e055347f67 半夜没事干,研究内核,作为我cocos2d-x的第一篇教程.cocos ...
- Cocos2d-x内存管理研究二
http://hi.baidu.com/tzkt623/item/46a26805adf7e938a3332a04 上一篇我们讲了内核是如何将指针加入管理类进行管理.这次我将分析一下内核是如何自动 ...
- cocos2dx多线程以及线程同步 与 cocos2dx内存管理与多线程问题
cocos2d-x引擎在内部实现了一个庞大的主循环,每帧之间更新界面,如果耗时的操作放到了主线程中,游戏的界面就会卡,这是不能容忍的,游戏最基本的条件就是流畅性,这就是为什么游戏开发选择C++的原因. ...
- 跟着石头哥哥学cocos2d-x(三)---2dx引擎中的内存管理模型
2019独角兽企业重金招聘Python工程师标准>>> 2dx引擎中的对象内存管理模型,很简单就是一个对象池+引用计数,本着学好2dx的好奇心,先这里开走吧,紧接上面两节,首先我们看 ...
- 【深入Cocos2d-x】探索Cocos2d-x中的内存管理-引用计数和自动释放池
2019独角兽企业重金招聘Python工程师标准>>> #深入Cocos2d-x-探索Cocos2d-x中的内存管理-引用计数和自动释放池 ###引用计数(Reference Cou ...
- cocos2dx标准容器_cocos2dx[3.2](24)——内存管理机制
[唠叨] 整合参考文档. [参考] [内存管理机制] 在3.x版本,Cocos2d-x采用全新的根类 Ref,实现Cocos2d-x 类对象的引用计数记录.引擎中的所有类都派生自Ref. 1.引用计数 ...
- cocos2d-x学习之自动内存管理
一.自动内存管理 1)概述 C++语言默认是没有提供自动内存管理的.使用者需要自己分配,自己释放.在cocos2d-x里提供了一个自动内存管理的方案.主要是通过CCObject来提供的,用户只要继承了 ...
最新文章
- UNITY录制视屏解决方案 - ShareREC For Unity3D
- SpringBatch 写xml文件(StaxEventItemWriter)用法(十四)
- git gui管理服务器配置文件,从 Git Gui 管理的Repository(库) 提交更改到 Bonobo服务器管理的Repository(库)...
- 一个帮助我100%拿offer的面试学习法
- Centos下载地址
- 点击高德地图标注没法弹窗_如何在地图上标注我的店铺
- 什么不用 iframe 做微前端
- Android NDK之JNI陷阱
- python怎样安装wordcloud(词云)文件
- java插件不启动_java-插件安装后Eclipse启动问题
- QT实现简单的浏览器
- Qt 读写 txt 文件
- ubuntu18.04 安装扫描仪驱动程序
- 电子技术基础(三)_第2章放大电路原理__晶体三极管与场效应三极管
- 计算机应用基础网课作业答案,知到网课答案计算机应用基础(新)全部答案
- 阿里云oss使用cdn,节省oss下行流量
- android audiorecord插上耳机录音由dmic切换到耳机录音
- windows录屏_Windows及苹果电脑录屏攻略
- 如何进行文献检索和阅读(转)
- 各省份非金融类对外直接投资存量(2003-2020年)
热门文章
- imgaug数据增强神器:增强器一览
- 面试时如何回答为何离开老东家
- 【组播技术入门 02】组播IP地址及组播MAC地址
- 如何将大的pdf文件,压缩至2Mb以内【免费,别想让我花钱!】
- Doctype作用? 严格模式与混杂模式如何区分?它们有何意义? 以及如何触发这2种模式?
- 5G跌下神坛,相比4G可用的技术较有限,唯一的优势就是速度快一些
- 柯杰下赢机器人_柯洁复出再战AI,这次是真正的机器人棋手!
- 牛顿法的简单介绍及Matlab实现
- 法律网推荐(二) 用Pig进行数据预处理
- 【钉钉小程序】报错提示“无跨域调用权限”