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

本章节介绍如下:

1.自动释放机制

        2.几个常用的宏,属性的get/set


这篇的内容是上一篇中遗留下来的,在介绍自动内存释放机制之前我们还得介绍一下Cocos2d-x中的引用计数机制。上篇中的引用计数机制是我们模仿Cocos2d-x写的,现在我们来跟踪下源码,更加升入的理解一下Cocos2d-x的机制

好了,废话有点多了,现在我们上代码,

HelloWorld.cpp中的init方法改成如下:

CCSprite* sprite= new CCSprite();
	sprite->initWithFile("Icon.png");
	CCLOG("%d",sprite->retainCount());
	this->addChild(sprite);
	CCLOG("%d",sprite->retainCount());
	sprite->release();
	CCLOG("%d",sprite->retainCount());
我们来分析一下,

1.我们自己采用NEW创建了一个精灵(不是CCSprite::create()

首先我们创建精灵,精灵是继承CCObject的,我们找到CCObject的构造函数,看看其中是不是有

CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1
, m_uAutoReleaseCount(0)
{
    static unsigned int uObjectCount = 0;

    m_uID = ++uObjectCount;
}

表示我们已经将引用计数初始为1了


2.设置了精灵图片

3.输出计数是1

4.我们将精灵增加到层中

(接着,我们光标定位到  this->addChild(sprite);   addChild上,按F12,一直跟进去,其中有一句  this->insertChild(child, zOrder);   

在F12进入方法 insertChild 中,在  ccArrayAppendObjectWithResize  ,在 ccArrayAppendObject   这里比较深,不是视频,所以不知道怎么表达。

一直进来之后我们将会看到

void ccArrayAppendObject(ccArray *arr, CCObject* object)
{
    CCAssert(object != NULL, "Invalid parameter!");
    object->retain();
	arr->arr[arr->num] = object;
	arr->num++;
}
所以,addChild方法会给引用计数加1,object->retain();   懂???这里计数是2

)

5.输出计数是2

6.释放精灵

(这里不用介绍了吧??)

7.输出计数是1


现在问题来了,打起精神哦

最终,在我们代码执行完后,最后输出的计数是1,说明我们的精灵其实是没有真正释放的。所以有内存浪费了,但是我们这样写是没问题的,不信你自己释放两次看看是不是会出错???

     原因就在于,我们释放了之后,其实最后层还会调用我们创建的精灵来进行渲染,如果这时候你释放完了,那么渲染的时候将找不到我们的精灵,所以会报错,那么精灵真正释放是在什么时候呢??


 还记得我们跟踪addChild方法的时候又insertChild这个方法吗?

 有这么一句话  ccArrayAppendObjectWithResize(m_pChildren->data, child);

我们理解的其实就是讲child添加到m_pChildren数组中,这是在CCNode类中,我们的精灵也是继承与它的

那么我们来看看CCNode类的析构函数

if(m_pChildren && m_pChildren->count() > 0)
    {
        CCObject* child;
        CCARRAY_FOREACH(m_pChildren, child)
        {
            CCNode* pChild = (CCNode*) child;
            if (pChild)
            {
                pChild->m_pParent = NULL;
            }
        }
    }

    // children
    CC_SAFE_RELEASE(m_pChildren);

所以说最终我们的精灵是在CCNode析构的时候释放的,注意这里有个宏  CC_SAFE_RELEASE  这其实就是安全释放,其代码按F12能看到,就不介绍了,removeChild() 引用计数减1   有兴趣的自己跟踪一下源码。。。


总算是把引用计数介绍完了,理解了没??没理解的话可不行哦,自己多跟踪几遍


1.我们接下来介绍自动释放池:

我们改写INIT方法

bool HelloWorld::init()
{
	//
	// 1. super init first
	if ( !CCLayer::init() )
	{
		return false;
	}
	CCSprite* sprite= CCSprite::create("Icon.png");
	CCLOG("%d",sprite->retainCount());
	this->addChild(sprite);
	CCLOG("%d",sprite->retainCount());
	return true;
}
将会看到输出:

1

2

呵呵,我知道大家在想什么,那么按照你们的想法,在return true;之前加上这么一句??

sprite->release()

报错??

原因在这,我们进入create方法中


autorelease方法,看名字就知道是自动释放,至于原理是什么?自己有时间跟踪一下吧,我C++不是很懂,跟踪得云里雾里的

总之只要记住,调用了自动释放的方法之后我就不需要手动管理了


还有一点点这节就完了,不要睡觉哦

2. 常用的get/set宏

不管是.net还是Java,我想大家对get、set不陌生吧?.net很方便  直接prop然后两下Tab键就可以了,Eclipse中也有快捷键,只是两种语言表达的方式不一样,java是提供出一个get+字段名的方法和set+字段名的方法,呃!表达的不清楚,不过搞Java的挨踢懂的。

.net下就如public int age{get;set;}

C++中就苦逼了,没有快捷键生成,所以Cococs2d-x提供了几个宏,好了  我们打开

E:\Cocos2D-XTool\cocos2d-x-2.2.3\cocos2dx\platform\CCPlatformMacros.h

这个文件


Ctrl+F   搜索CC_SYNTHESIZE


这里我们就稍微介绍几个常用的,当然,还有很多在这个文件里面,有时间在慢慢摸索吧

CC_SYNTHESIZE

我们在新建项目,在添加如下两个文件


头文件代码


源文件代码


HelloWorldScene.cpp


我们是不是没有在源文件中写setNumber等方法??这就是宏的作用,使我们能少些很多代码


现在我们将代码改成如下



分析一下  首先我们将sPrite赋值给成员变量Number,Number这时候执行一块内存空间,接下来我们在把sPrite2赋值给它 

现在Number指向sPrite2,而sPrite此时并没有释放,所以会发生内存泄露,当然我们可以手动释放,但是项目大了的时候,谁能注意到这些??

就算我们用CCSprite::create的方式创建的精灵,内存不需要我们管,但是它的autorelse不是马上就释放的,而是要等到另一条消息进入的时候它才遍历没用的进行释放。所以内存泄露还是会产生


Cocos2d-x就为我们准备了另外一个宏


我们换成CC_SYNTHESIZE_RETAIN就可以了,自己理解一下用红色圈圈圈起来的代码,

1.首先我们将sPrite赋值

2.这是将判断,条件成立,执行CC_SAFE_RETAIN(var),   var就是我们的形参sPrite,此时sPrite的计数为2了

3.然后再CC_SAFE_RELEASE,我们没有给Number初始化,所以为null ,没有内存空间,如果直接number->release()会报错的,

这里我们用了安全释放的宏,自己可以看一下源码

4.这是我们把形参赋给Number,此时Number和sPrite执行一块区域,刚好计数又是2.

5.接下来我们把sPrite1赋值,

6.sPrite1执行了RETAIN   计数为2

7.Number relese   计数是1,因为sPrite还在

8.sPrite1和Number计数为2


总算是介绍完了,总结


1.自动释放,只需要调用一下autorelese就可以了

2.注意一下get/set宏,以及CC_SYNTHESIZE_RETAIN和其它的区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值