码迷,mamicode.com
首页 > 其他好文 > 详细

cocos2d-x内存管理

时间:2014-08-01 13:45:51      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   io   2014   


1、首先我们必须说一下c++中变量的内存空间的分配问题,我们在c++中写一个类,可以在栈上分配内存空间也可以使用new在堆上分配内存空间,如果类对象是在栈上分配的内存空间,这个内存空间的管理就不是我们的事了系统会自动回收,但如果是在堆上分配的内存空间,当然需要我们来手动的delete了!cocos2dx采用的是在堆上分配内存空间,所以问题来了,既然在堆上分配内存空间,那么如何管理这个内存空间,什么时候应该释放就是个问题了!这就是下面要说的重点,cocos2dx引入了引用计数这个内存管理机制。
简单说下,内存管理机制,
    //对象创建的时候引用计数被设置为1,这个是在它的构造函数中完成的,它会先调用父类CCOjbect的构造函数
    //CCObject的构造函数如下所示
    //CCObject::CCObject(void)
    //, m_uReference(1) {}// when the object is created, the reference count of it is 1

    Sprite * sprite = new Sprite();
 
    Log("retain count:%d",sprite->retainCount());  //此时输出的值为1,new以后就会被加1
 
    //调用retain方法的时候引用计数增加1
    sprite->retain();
    Log("retain count:%d",sprite->retainCount());  //次数输出值为2
 
    //调用release方法的时候引用计数减一,当这个引用计数减为0的时候,在release方法中会delete掉这个对象
    sprite->release();
    Log("retain count:%d",sprite->retainCount()); //此时输出的值为1
    //当我们调用autorelease方法的时候会调用这段代码
    // PoolManager::getInstance()->getCurrentPool()->addObject(this);
    //调用autorelease方法的时候对象会被放到自动回收池中,这个自动回收池在每帧结束的时候会调用一次对象的release方法
    sprite->autorelease();
    Log("retain count:%d",sprite->retainCount());  //注意输出值为1,autorelease在帧结束时调用,所以在下一帧开始前对象就被删除
上边的代码有一处不是很好的理解,就是大家经常说的自动回收机制,也就是上边的autorelease方法,这个方法到底为我们做了什么,有什么作用,我们需要好好的搞清楚!首先需要澄清的一个概念就是帧,我们经常的说每秒多少多少帧,其实这个帧需要多少时间不是固定的,这个需要看每帧我们需要做多少事情,如果每一帧我们需要渲染很多的东西,那这一帧执行的时间当然就会很长的,游戏显得就会很卡,这个时候每秒的帧率就会下降的,所以不是时间决定的帧率,而是帧影响的时间!这个自动回收池就是在每帧结束的时候起作用的,在游戏的每一帧都会有一个大的循环,在一帧开始之前,系统建立了一个内存回收池,在这一帧的过程中,当我们调用了autorelease方法以后,我们的对象就会放到这个内存回收池中,当一帧结束的时候这个内存回收池就会释放掉,这个时候在内存回收池中的对象就会被release一下,也就是说引用计数就会减一,如果这个时候引用计数为0,就会删除对象了。如果引用计数不为0的话对象是不会被删除的,下一帧开始的时候系统又会创建一个内存回收池,这个时候在上一次添加的对象这个时候是不会重新添加到这个内存回收池中的,在这个内存回收池中的对象是你在这一帧中调用了autorelease函数的对象。好了,内存回收池我觉的我已经说清楚了。下面我们来看一下,通常我们的代码都是怎么写的,来看看这个自动回收机制怎么就做到自动回收了!

//在create的时候调用了sprite的autorelease方法
Sprite * sprite = Sprite::create("HelloWorld.png");
Log("retain count:%d",sprite->retainCount()); //retain 1 此时还不是帧的结束时内存自动回收池还不会去释放
this->addChild(sprite);  //会自动调用<span style="font-family: Arial, Helvetica, sans-serif;">retain()方法</span>
Log("retain count:%d",sprite->retainCount()); //retain 2

首先我们需要分析一下上边的代码,调用了create工厂方法以后,内部的实现是先new一个Sprite的对象,这个时候引用计数加1,然后调用autorelease方法,将这个对象放到了自动回收池中,因为这一帧还没有结束,当然引用计数就还是1,所以打印的结果就是1,当我们调用addChild的时候,传入这个Sprite对象,这个时候在当前层接受了这个对象以后会把它的引用计数加一,表明当前层正在使用这块内存空间,所以现在的retain就是2了。当这一帧结束的时候自动回收池会将对象的引用计数-1,所以现在就只有Layer在引用这个对象了,当Layer析构的时候,它会调用这个对象的release方法,这个时候当然就会删除了这个Sprite对象了。所以什么是自动回收机制呢,自动就是在这一帧结束的时候将对象开始new的时候加的那个引用计数减掉,而让引擎中持有对象引用的其他类去管理这个对象,当持有者析构的时候就删除引用,引擎中的类负责retain和release,这个也算是自动吧!下面我们通过俩个例子来理解一下这个内存管理机制

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
 
    MenuItemImage *pCloseItem = CCMenuItemImage::create(
            "CloseNormal.png",
            "CloseSelected.png",
            this,
            menu_selector(HelloWorld::menuCloseCallback));
 
    Menu* pMenu = Menu::create(pCloseItem, NULL);
    this->addChild(pMenu, 1);
 
    this->m_sprite = CCSprite::create("HelloWorld.png");
    Log("%d",this->m_sprite->retainCount());
    return true;
}

//按钮的响应事件
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCLog("%d",this->m_sprite->retainCount());
    this->m_sprite->getPosition();
}

好了,运行程序我们会发现程序崩溃了,我们来分析一下。当我们创建了CCSprite对象的时候引用计数为1,并且该对象被放到了内存回收池中,在这一帧以后就会release对象一次,这个时候引用计数为0的对象当然就被释放了,我们按下按钮去调用这个对象,内存已经释放掉了,程序能不崩溃吗?下面我们来将代码改成如下的这样,看看效果。


this->m_sprite = CCSprite::create("HelloWorld.png");
Log("%d",this->m_sprite->retainCount());
this->m_sprite->retain();  //或者this->addchild(m_sprite); //都会使m_sprite引用计数加1
Log("%d",this->m_sprite->retainCount());

这个时候运行起来程序,在按钮的函数调用的时候你会看到输出的引用计数都是1,因为我们已经手动的retain了一下这个对象,虽然自动回收池将它release了一下,但是它的引用计数任然为1。既然我们retain了,所以在层析构的时候记得要release啊(如果是在场景中addchild释放用removechild。当然场景也可以removeAllChild。就可以释放所有addchid所有资源了)。这样内存才不会泄露!所以在开发中建议使用create去创建实例,如果你是new出来的要记得,delete。

可以加群,共同学习  373364032 3

cocos2d-x内存管理,布布扣,bubuko.com

cocos2d-x内存管理

标签:style   blog   http   color   使用   os   io   2014   

原文地址:http://blog.csdn.net/st75033562/article/details/38332527

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!