Cocos2d-x开发中Ref内存管理

  次阅读 来源:互联网(转载协议) 2015-09-27 15:25 我要评论(0)

Ref类是Cocos2d-x根类,Cocos2d-x中的很多类都派生自它,例如,我们熟悉的节点类Node也派生自Ref。我们介绍Ref内存管理。

内存引用计数

Ref类设计来源于Cocos2d-iphone的CCObject类,在Cocos2d-x 2.x中也叫CCObject类。因此Ref类的内存管理是参考Objective-C手动管理引用计数(Reference Count)而设计的。

如图所示是内存引用计数原理示意图。每个Ref对象都有一个内部计数器,这个计数器跟踪对象的引用次数,被称为“引用计数”(Reference Count,简称RC)。当对象被创建时候,引用计数为1。为了保证对象的存在,可以调用retain函数保持对象,retain会使其引用计数加1,如果不需要这个对象可以调用release函数,release使其引用计数减1。当对象的引用计数为0的时候,引擎就知道不再需要这个对象了,就会释放对象内存。

引用计数实例如图所示,我们在ObjA中使用new等操作创建了一个Ref对象,这时候这个对象引用计数为1。然后在OjbB中使用retain函数保持Ref对象,这时引用计数为2。再然后ObjA中调用release函数,这时引用计数为1。在ObjB中调用release函数,这时引用计数为0。这个时候Ref对象就会由引擎释放。

在Ref类中相关函数有:retain()、release()、autorelease()和getReferenceCount()。其中autorelease()函数与release()函数类似,它会延后使引用计数减1,autorelease()我们稍后再介绍。getReferenceCount()函数返回当前的引用计数。

自动释放池

我们先看看下面的代码片段。XmlParser * XmlParser::createWithFile(const char *fileName)

{

XmlParser *pRet = new XmlParser();

// ①

return pRet;

}

上述代码XmlParser::createWithFile(const char *fileName)函数能够创建XmlParser对象指针并返回给调用者。根据我们前面介绍的C++使用new规则,在XmlParser::createWithFile函数中还应该释放对象的语句,如果没有,那么每次调用者调用XmlParser::createWithFile函数都会创建一个新对象,老的对象没有释放,就会造成内存泄漏。但是如果我们在第①行代码,添加释放语句pRet->release(),那么问题可能会更严重,返回的对象可能已经被释放,返回的可能是一个野指针。

自动释放池(AutoReleasePool)正是为此而设计,自动释放池也是来源于Objective-C,Cocos2d-x中维护AutoreleasePool对象,它能够管理即将释放的对象池。我们在第①可以使用pRet->autorelease()语句,autorelease()函数将对象放到自动释放池,但对象的引用计数并不马上减1,而是要等到一个消息循环结束后减1,如果引用计数为0(即,没有被其它类或Ref对象retain),则释放对象,在此之前对象并不会释放。

消息循环是游戏循环一个工作职责,消息循环说到底还是游戏循环,消息循环是接收事件,并处理事件。自动释放池的生命周期也是由消息循环管理的。如图所示,图中“圈圈”是消息循环周期,它的一个工作职责是维护自动释放池创建和销毁。每次为了处理新的事件,Cocos2d-x引擎都会创建一个新的自动释放池,事件处理完成后,就会销毁这个池,池中对象的引用计数会减1,如果这个引用计数会减0,也就是没有被其它类或Ref对象retain,则释放对象,否则这个对象不会释放,在这次销毁池过程中“幸存”下来,它被转移到下一个池中继续生存。

下面我们看一个实例,下面代码是13.2.2一节的实例HelloWorldScene.cpp代码:bool HelloWorld::init()

{

if ( !Layer::init() )

{

return false;

}

Size visibleSize = Director::getInstance()->getVisibleSize();

Vec2 origin = Director::getInstance()->getVisibleOrigin();

auto goItem = MenuItemImage::create(

go-down.png,

go-up.png,

CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

goItem->setPosition(Vec2(origin.x + visibleSize.width - goItem->getContentSize().width/2 ,

origin.y + goItem->getContentSize().height/2));

auto menu = Menu::create(goItem, NULL);①

本站文章信息来源于网络以及网友投稿,本站只负责对文章进行整理、排版、编辑,是出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。如果您有什么意见或建议,请联系QQ28-1688-302!

人工智能实验室
相关文章相关文章
  • 汤晓鸥:人工智能的中国式文艺复兴

    汤晓鸥:人工智能的中国式文艺复兴

  • 马云的新零售?张近东的智慧零售?抑或是刘强东的第四次零售革命?

    马云的新零售?张近东的智慧零售?抑或是刘强东的第四次零售革命?

  • 全球陷入"区块链狂热"潮,大规模应用还需等待

    全球陷入"区块链狂热"潮,大规模应用还需等待

  • 区块链最近太火,但A股多家公司明确表态不考虑涉足

    区块链最近太火,但A股多家公司明确表态不考虑涉足

网友点评网友点评
阅读推荐阅读推荐

算法 任何一个入门的软件开发人员都会听到这句话:算法是软件的灵魂!近年来大火的机器学习即是在算法在人工智能上的集中体现。今日头条通...

据《日本经济新闻》报道,日本东京大学教授稻叶雅幸等人开发出再现日本人骨骼肌肉构造的机器人。机器人各部位的肌肉和骨骼长度与日本人的平...

以奥黛丽-赫本为原型打造的人形机器人索菲娅首次拜访了印度。索菲娅是世界上首位获得公民身份的机器人,她在12月30日出现在了印度理工学院...

在查获现场,代售点电脑旁的一台机器人通过敲击电脑键盘抢票。 广州日报惠州讯 (全媒体记者秦仲阳 通讯员张中铃摄影报道)2018年春运售票已...