Cocos2dx之为什么会有自动内存池
发布时间:2020-12-14 16:37:41 所属栏目:百科 来源:网络整理
导读:对Cocos2dX的内存管理不了解的人会有这样的疑惑,Cocos2dX的自动内存池是干什么的?当调用一个对象的autorelease后,该对象就被加入到自动内存池中。那是否意味着我们可以不用再去对该对象进行retain,release了呢? 答案是错的。自动内存池只作用于那些”创
对Cocos2dX的内存管理不了解的人会有这样的疑惑,Cocos2dX的自动内存池是干什么的?当调用一个对象的autorelease后,该对象就被加入到自动内存池中。那是否意味着我们可以不用再去对该对象进行retain,release了呢? 答案是错的。自动内存池只作用于那些”创建期“的对象,也就是说对于那些用create函数创建出来的对象,实际上是调用了autorelease,而autorelease会把该对象加入到自动内存池中,而在用create函数创建了对象后的那一帧,当前自动内存池中的所有对象都会被release一次,然后清空该自动内存池。下面是分析过程: 一.create函数的内幕使用create函数创建对象实际上会调用autorelease,而autorelease又会将该对象加入到当前自动内存池中: #define CREATE_FUNC(__TYPE__) static __TYPE__* create() { __TYPE__ *pRet = new(std::nothrow) __TYPE__(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } } Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addObject(this); return this; } 二.为什么会有自动内存池
我们来看下每帧中自动内存池会执行什么:
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // create the application instance AppDelegate app; return Application::getInstance()->run(); } int Application::run() { PVRFrameEnableControlWindow(false); // Main message loop: LARGE_INTEGER nLast; LARGE_INTEGER nNow; QueryPerformanceCounter(&nLast); initGLContextAttrs(); // Initialize instance and cocos2d. if (!applicationDidFinishLaunching()) { return 1; } auto director = Director::getInstance(); auto glview = director->getOpenGLView(); // Retain glview to avoid glview being released in the while loop glview->retain(); while(!glview->windowShouldClose()) { QueryPerformanceCounter(&nNow); if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % _animationInterval.QuadPart); director->mainLoop(); glview->pollEvents(); } else { Sleep(1); } } // Director should still do a cleanup if the window was closed manually. if (glview->isOpenGLReady()) { director->end(); director->mainLoop(); director = nullptr; } glview->release(); return 0; } run函数中有这么一句,director->mainLoop(),跟踪进去: void DisplayLinkDirector::mainLoop() { if (_purgeDirectorInNextLoop) { _purgeDirectorInNextLoop = false; purgeDirector(); } else if (_restartDirectorInNextLoop) { _restartDirectorInNextLoop = false; restartDirector(); } else if (! _invalid) { drawScene(); // release the objects PoolManager::getInstance()->getCurrentPool()->clear(); } } void AutoreleasePool::clear() { #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) _isClearing = true; #endif std::vector<Ref*> releasings; releasings.swap(_managedObjectArray); for (const auto &obj : releasings) { obj->release(); } #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) _isClearing = false; #endif } 调用releasings.swap(_managedObjectArray)后当前自动内存池中就被清空了。 for (const auto &obj : releasings) { obj->release(); }创建一个对象时,该对象的引用计数被初始化为1,如果我们没有对该对象进行retain操作,或者没有使用它(也就是没有其它对象引用它),那么该对象的引用计数则为1,调用上面的代码后,该对象的引用计数变为0,之后便不复存在。 结论:
自动内存池只作用于创建期的对象,也就是刚用create函数创建的对象。如果我们没有使用它,或者没有进行retain操作,那它下一帧就会被清除。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |