记录一下Cocos2dX中内存管理的理解和试验
2014-05-05 23:06
537 查看
记录一下Cocos2dX中内存管理的理解和试验
一直弄C++的,还经常到底层晃荡滴,十分不习惯内存这么宝贵的资源不受自己控制的编程,就像大热天坐在电脑前打游戏,边上千把只蚊子飞来飞去一样难受。尤其是那个autorelease,大把的兄弟们分析了它的排队和删除机制了,但私心里总想,自己造出来的东西,为毛不能我想让它滚蛋就滚蛋,总在内存里挂着作甚。虽然autorelease这种机制确实有它的优点,但也没必要到处都用吧……,手机内存现在也不便宜啊。
一、我们的目标
C++的方式一般是new、delete成对用,我们的目标也就是这个,告别静态方法,告别 CREATE_FUNC宏,告别autorelease retain release,重要的是,autorelease的队列中不要加入我们不想加入的东西。
二、一点点摘吧出来
[align=justify] 首先装模作样的管理一下内存,一般来说,Cocos2dx如此打包的原因估计就是想让内存管理更加简单,于是推着大伙使用静态create方法,在这个方法中,实际使用new实例了对象,并且随后调用autorelease将其排队了。通常我们不用retain和release,因为一般大伙儿把这货造出来都是为了addchild的,在addchild里面实际做了一次retain,然后在使用结束的某个地方removechild的时候(没去找,可能是析构,又release了一下)。我们在这里试图让autorelease失去作用,于是构造时retain一下,析构时release一下,基本做到我想放的时候放,当然不一定掉了)[/align]
其次是避免使用静态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了。
哈哈,首先解决个人习惯问题,后面爬起代码来才会爽。
一直弄C++的,还经常到底层晃荡滴,十分不习惯内存这么宝贵的资源不受自己控制的编程,就像大热天坐在电脑前打游戏,边上千把只蚊子飞来飞去一样难受。尤其是那个autorelease,大把的兄弟们分析了它的排队和删除机制了,但私心里总想,自己造出来的东西,为毛不能我想让它滚蛋就滚蛋,总在内存里挂着作甚。虽然autorelease这种机制确实有它的优点,但也没必要到处都用吧……,手机内存现在也不便宜啊。
一、我们的目标
C++的方式一般是new、delete成对用,我们的目标也就是这个,告别静态方法,告别 CREATE_FUNC宏,告别autorelease retain release,重要的是,autorelease的队列中不要加入我们不想加入的东西。
二、一点点摘吧出来
#include "GameScene.h" GameScene::GameScene(void) { backgroud = Sprite::create("HelloWorld.png"); backgroud->retain(); } GameScene::~GameScene(void) { backgroud->release(); } void GameScene::InitLayer() { Layer::init(); this->addChild(backgroud); }
[align=justify] 首先装模作样的管理一下内存,一般来说,Cocos2dx如此打包的原因估计就是想让内存管理更加简单,于是推着大伙使用静态create方法,在这个方法中,实际使用new实例了对象,并且随后调用autorelease将其排队了。通常我们不用retain和release,因为一般大伙儿把这货造出来都是为了addchild的,在addchild里面实际做了一次retain,然后在使用结束的某个地方removechild的时候(没去找,可能是析构,又release了一下)。我们在这里试图让autorelease失去作用,于是构造时retain一下,析构时release一下,基本做到我想放的时候放,当然不一定掉了)[/align]
其次是避免使用静态create方法。
AppDelegate::AppDelegate() { } AppDelegate::~AppDelegate() { //pMainLayer->release(); delete pMainLayer; } bool AppDelegate::applicationDidFinishLaunching() { // initialize director auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLView::create("My Game"); director->setOpenGLView(glview); } // turn on display FPS director->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); // create a scene. it's an autorelease object auto gamescene = Scene::create(); gamescene->addChild(pMainLayer); pMainLayer = new GameScene(); pMainLayer->InitLayer(); director->runWithScene(gamescene); return true; }
这里稍有些不严谨,本来应该构造和析构对应,但显然层对象在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一样。但是编译器不干,为什么呢?
/// @} CC_CONSTRUCTOR_ACCESS: Sprite(void); virtual ~Sprite(void); /* Initializes an empty sprite with nothing init. */ virtual bool init(void); /** * Initializes a sprite with a texture. * * After initialization, the rect used will be the size of the texture, and the offset will be (0,0). * * @param texture A pointer to an existing Texture2D object. * You can use a Texture2D object for many sprites. * @return true if the sprite is initialized properly, false otherwise. */ virtual bool initWithTexture(Texture2D *texture);
看看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了。
哈哈,首先解决个人习惯问题,后面爬起代码来才会爽。
bool AppDelegate::applicationDidFinishLaunching() { //初始化OpenGL auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLView::create("My Game"); director->setOpenGLView(glview); } // turn on display FPS director->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); //创建场景,场景是自释放的对象 Scene* gamescene = Scene::createW 4000 ithPhysics(); //游戏主界面层 pMainLayer = new GameLayer(); gamescene->addChild(pMainLayer); //pMainLayer->InitLayer(); director->runWithScene(gamescene); return true; } //GameLayer继承自Layer GameLayer::GameLayer(void) { Layer::init(); Size ContentSize = this->getContentSize(); background = new LRole(); background->init("HelloWorld.png"); background->setPosition(ContentSize.width/2.0f,ContentSize.height/2.0f); this->addChild(background); } GameLayer::~GameLayer(void) { this->removeChild(background); delete background; } //LRole继承自Sprite LRole::LRole(void) { } LRole::~LRole(void) { } bool LRole::init(const string& filename) { return initWithFile(filename); }
相关文章推荐
- 记录一下Quick-Cocos2dx-Community lua绑定C++自定义类遇到的问题
- 简单记录一下简单的理解
- cocos2dx 使用过程中内存管理的理解
- 什么是泛型?简单记录一下自己理解的泛型。
- cocos2dx内存管理的个人理解
- cocos2dx 内存管理的理解
- 记录一下: 理解 __declspec(dllexport)和__declspec(dllimport)
- 三分钟理解cocos2dx的内存管理
- 北理工java的试卷总结,我做了一下,发现也有许多以前没有理解的地方,现在再次记录下来
- 记录一下从懵懂到理解RESTful的过程
- cocos2dx 3.2 学习篇之五(简单理解内存管理)
- 记录一下对service生命周期的理解
- oauth2 原理和理解(转载阮一峰的记录一下,后面自己再总结)
- 1063 sicily (木有准确理解题意,一直wrong error)——不过这事快速排序的一次复习,还是记录一下
- 快速记录一下cocos2dx 3.x 全屏幕 blur 效果实现相关代码
- 关于spring切面的一点理解,记录一下
- 关于c#的config配置文件操作网上很多讲的和实际运用感觉不符,终于理解了一点点,记录一下
- CentOS安装redis-audit 但执行时出错未解决 记录一下安装过程
- 试验一下
- 试验网站#3搜索引擎优化收录情况记录2007-7-29