自动内存管理,这个词本人第一次看到在oc编程当中看到的,一开始觉得挺神奇的,因为不了解嘛,一个学C++出生的孩子,看到这么高级的东西吓尿了。不过现在把这套机制移植到cocos2dx里面以后,看了众大神们的解释以后,发现其实也没有那么神奇。不说深入理解,至少知道个大概皮毛,知道自己 sprite->autorelease(),sprite->retain()等等在做什么了。
C++的动态内存管理一般建议遵循谁申请谁释放的原则,即谁通过new操作符创建了对象,谁就负责通过delete来释放对象。而且new和delete必须成对出现。new很方便,即要用时候new一下对象就可以了,但是我们很难判断什么时候该去delete这个对象。可以一个对象被多个地方使用,如果一个地方用完了这个对象以后,觉得没用了,就把这个对象给释放了。但是其他地方却仍然引用这个对象,这样你就把别人用的这块公共区域给释放掉了,别人还怎么用啊! 所以!!!为了解决这个问题,聪明的人类用计数器的方法来统计有多少地方用了这个对象。
以下是我个人理解+适当比喻,方便大家理解哈 :
我们把在堆上 开辟 空间比喻做 租房子吧,new操作呢对应就是 拿到房门钥匙,可以进入房门, 而delete对应的就是房间已经不要租了,可以把钥匙还给房东了(如果不操作这个后果很严重,房东以为你续租,不租给别人,你又不用,白白浪费了很多资源)。 那计数器其实就是有多少人要用这个房间,我们简化租房中间过程,假设如果一个人要用这个房间就是一直呆在房间里面,走出房间了就代表已经用完房间,不要用房间了!这样的话,我们就可以把计数器简单认为是在房间的人数量!这样就很显而易见,当房间里面没人了的时候,即计数器为 0 的时候,我们就可以把房门钥匙还给房东了。不要租房间了,即这个时候我们就可以把我们申请的动态空间还给堆了。
但是!!!这边细心的程序猿一定会发现!这个有bug,在房东给你钥匙后的一小段时间里,房间里怎么可能会有人!所以刚刚交给你钥匙的瞬间,不就已经同时已经退还了房间了嘛!!
当然不会,要不然人家也不好意思开发这个自动管理内存模块了。
好,上面我们用租房子的比喻解释清楚了自动内存管理机制,接下来我们回到现实,回到编程生涯。首先为了不让系统自己一下子就把刚刚分配的空间自动回收回去!我们在创建的时候,默认把计数器设置为1 ,但是有个问题,实际这个时候没有任何地方引用到这个对象,我们必须把这个平白无辜多出来的东西在适当的时候给减掉。这个 1 必须减掉!但是不是刚刚生成的现在,在cocos2dx采用的是在这一帧结束的时候。而这个在这一帧结束的去减 1 的操作并不是平白无故就会给你做的,他是需要你去给予代码的! 这个对应的代码就是 sprite->autorelease();
可能有些人就要困惑了!!! 你说错了!!就连cocos2dx的自带hello world代码都没->autorelease()操作呢!!为什么!!!
好,上代码为证!
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
//创建一个空白场景
auto scene = Scene::create();
// 'layer' is an autorelease object
//创建一个helloWorld图层,蹦添加到空白场景中。
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
这段代码就充分表明!根本就没有autorelease()这个!!!
好~~~这边先解释以下,大家可以选中create()函数,跳入他的实现代码。可能需要跳两次。之后你就会神奇发现这段代码:
Scene* Scene::create()
{
Scene *ret = new Scene();
if (ret && ret->init())
{
ret->autorelease();
return ret;
}
else
{
CC_SAFE_DELETE(ret);
return nullptr;
}
}
好,上面代码就可以证明为所说的,在创建新物件时候,会自带一个autorelease()函数。
但是!!并不是所有时候,系统都会给你自动添加autorelease()的!在某些时候是需要我们自己去使用,比如你去申请一个新按钮选择的语法是这样的。
首先新建一个按钮对象 Button* button = new Button(); 然后你给他添加各种状态下的纹理,然后!!!这个必须的时刻,你就要去autorelease()了。。。原因很简单,其实就是你自己用代码去实现crete()函数,crete()里面有autorelease,你当然也要去添加啦。
上面已经基本解释清楚了自动内存管理的基本内容了,那有些人有奇葩需求,比如说,我现在创建好按钮,可能我n帧以后才会知道谁要引用它,我们上面也说了,这一帧结束会被autorelease()掉,如果这一帧没人引用它就被自动销毁了,那我n帧以后再去引用不就会产生找不到指定内存了么!!!
不要慌,聪明的人类总有办法的,就连飞船都怕出故障,设置的自动制动和手动制动。cocos2dx也当然有手动内存干预管理啊,我既然这一帧没人引用它,我就让它计数器多+1(->retain())么,然后就始终不会变0 了么。。因为暂时没人引用它,自然也不会产生-1 的指令嘛,这样自然就可以等到来引用它的对象了。 但是千万记得,我们+1(->retain())了不是白白加的,我们还得手动去 -1(->release()),这样的话这个对象就不会永久无法删除了。自然不会内存泄漏了。
还有一个一直忘记讲的,自动内存管理的管理的对象是 Ref ,即老版本的 CCobject,众所周知,所有的物件都是继承于这个基类的。
关于自动内存管理,本人的理解基本就是这样了,分享给大家。可能理解有偏差,欢饮大家指出错误,让我正确的成长哈~~~