欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

记录一下Cocos2dX中内存管理的理解和试验

程序员文章站 2022-05-13 12:08:25
...

记录一下Cocos2dX中内存管理的理解和试验 一直弄C的,还经常到底层晃荡滴,十分不习惯内存这么宝贵的资源不受自己控制的编程,就像大热天坐在电脑前打游戏,边上千把只蚊子飞来飞去一样难受。尤其是那个autorelease,大把的兄弟们分析了它的排队和删除机制了

记录一下Cocos2dX中内存管理的理解和试验

一直弄C++的,还经常到底层晃荡滴,十分不习惯内存这么宝贵的资源不受自己控制的编程,就像大热天坐在电脑前打游戏,边上千把只蚊子飞来飞去一样难受。尤其是那个autorelease,大把的兄弟们分析了它的排队和删除机制了,但私心里总想,自己造出来的东西,为毛不能我想让它滚蛋就滚蛋,总在内存里挂着作甚。虽然autorelease这种机制确实有它的优点,但也没必要到处都用吧……,手机内存现在也不便宜啊。

一、我们的目标

C++的方式一般是new、delete成对用,我们的目标也就是这个,告别静态方法,告别 CREATE_FUNC宏,告别autorelease retain release,重要的是,autorelease的队列中不要加入我们不想加入的东西。

二、一点点摘吧出来

首先装模作样的管理一下内存,一般来说,Cocos2dx如此打包的原因估计就是想让内存管理更加简单,于是推着大伙使用静态create方法,在这个方法中,实际使用new实例了对象,并且随后调用autorelease将其排队了。通常我们不用retain和release,因为一般大伙儿把这货造出来都是为了addchild的,在addchild里面实际做了一次retain,然后在使用结束的某个地方removechild的时候(没去找,可能是析构,又release了一下)。我们在这里试图让autorelease失去作用,于是构造时retain一下,析构时release一下,基本做到我想放的时候放,当然不一定掉了)

其次是避免使用静态create方法。

这里稍有些不严谨,本来应该构造和析构对应,但显然层对象在App构造的时候构造会@#¥#%@,没有去研究为什么,所以在applicationDidFinishLaunching构造吧,在析构函数中放掉。

GameScene是继承Layer的类,实际就写了上面代码中那三个函数,就创建了一个Sprite贴进去而已。其中Scene的创建被我们拿到了AppDelegate中,没有集成到GameScene(虽然还叫这个名字),仍然用autorelease管理(使用静态方法创建)。我们主要看GameScene,可以发现,我们使用new实例化对象m_pMainLayer(类成员),直接调用了对象的构造函数,跟一下,实际就是调用了Layer::Layer(),申请了内存,但是没有autorelease,没有init。

那么,显然现在我们要管理如何放掉它了。如某些同学的说法,可以讲new和release对起来用,一开始我就是这么用的(注释中的内容),但实际情况是,直接用delete好了。现在看起来很像C++了吧,哈哈。

三、Sprite为什么没有用new、delete?

可能有兄弟已经注意到,Sprite,这个最需要我们精细管理的对象这里并没有使用new、delete。确实,一开始我想用来着,先new一个Sprite,然后用initWithFile载入图片,就像静态方法Create一样。但是编译器不干,为什么呢?

看看CCSprite的源码就知道了,CC_CONSTRUCTOR_ACCESS其实就是protect换张皮,换句话说,cocos2dx将new、delete保护起来了,不让用,必须autorelease。可以想见,Layer必然也是,那上面的Layer为什么可以?对了,只要继承一下就行了,此时内存完全由我掌控。

四、是不是有点作?

可能真是有点作吧,俗话说no zuo no die,可能有一天碰上莫名其妙的问题就是如此作出来的,所以立文为证,提醒自己一下。毕竟还是用惯了new、delete和自己亲力亲为的管理,强迫症使然,一个不用自己管的内存扔在那里总觉得这玩意指定泄露了。决定以后如此new、delete的来了,会不会有虾米问题?有木有高手指点一下?


五、现实报来得快

这两天搬家整房子,手头停了一段。今天捡起来按照前面“作”的内容完整的写下来才发现,原来还不仅仅是new delete受protect限制的问题,还有函数initWithFile,没办法,继承类里面加个公开函数包一下吧,这样外面就可以调用了。如何,下面这个是不是看起来舒服多了?如果还觉得不爽,重载个构造函数吧init替了吧,不过这样就只能ASSERT initWithFile返回True了。

哈哈,首先解决个人习惯问题,后面爬起代码来才会爽。