Cocos2dx之为什么会有自动内存池

前端之家收集整理的这篇文章主要介绍了Cocos2dx之为什么会有自动内存池前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

对Cocos2dX的内存管理不了解的人会有这样的疑惑,Cocos2dX的自动内存池是干什么的?当调用一个对象的autorelease后,该对象就被加入到自动内存池中。那是否意味着我们可以不用再去对该对象进行retain,release了呢?

答案是错的。自动内存池只作用于那些”创建期“的对象,也就是说对于那些用create函数创建出来的对象,实际上是调用了autorelease,而autorelease会把该对象加入到自动内存池中,而在用create函数创建了对象后的那一帧,当前自动内存池中的所有对象都会被release一次,然后清空该自动内存池。下面是分析过程:

一.create函数的内幕

使用create函数创建对象实际上会调用autorelease,而autorelease又会将该对象加入到当前自动内存池中:

  1. #define CREATE_FUNC(__TYPE__) \
  2. static __TYPE__* create() \
  3. { \
  4. __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
  5. if (pRet && pRet->init()) \
  6. { \
  7. pRet->autorelease(); \
  8. return pRet; \
  9. } \
  10. else \
  11. { \
  12. delete pRet; \
  13. pRet = NULL; \
  14. return NULL; \
  15. } \
  16. }

  1. Ref* Ref::autorelease()
  2. {
  3. PoolManager::getInstance()->getCurrentPool()->addObject(this);
  4. return this;
  5. }


二.为什么会有自动内存池

我们来看下每帧中自动内存池会执行什么:

  1. int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
  2. {
  3. UNREFERENCED_PARAMETER(hPrevInstance);
  4. UNREFERENCED_PARAMETER(lpCmdLine);
  5.  
  6. // create the application instance
  7. AppDelegate app;
  8. return Application::getInstance()->run();
  9. }

  1. int Application::run()
  2. {
  3. PVRFrameEnableControlWindow(false);
  4.  
  5. // Main message loop:
  6. LARGE_INTEGER nLast;
  7. LARGE_INTEGER nNow;
  8.  
  9. QueryPerformanceCounter(&nLast);
  10.  
  11. initGLContextAttrs();
  12.  
  13. // Initialize instance and cocos2d.
  14. if (!applicationDidFinishLaunching())
  15. {
  16. return 1;
  17. }
  18.  
  19. auto director = Director::getInstance();
  20. auto glview = director->getOpenGLView();
  21.  
  22. // Retain glview to avoid glview being released in the while loop
  23. glview->retain();
  24.  
  25. while(!glview->windowShouldClose())
  26. {
  27. QueryPerformanceCounter(&nNow);
  28. if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
  29. {
  30. nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % _animationInterval.QuadPart);
  31. director->mainLoop();
  32. glview->pollEvents();
  33. }
  34. else
  35. {
  36. Sleep(1);
  37. }
  38. }
  39.  
  40. // Director should still do a cleanup if the window was closed manually.
  41. if (glview->isOpenGLReady())
  42. {
  43. director->end();
  44. director->mainLoop();
  45. director = nullptr;
  46. }
  47. glview->release();
  48. return 0;
  49. }

run函数中有这么一句,director->mainLoop(),跟踪进去:
  1. void DisplayLinkDirector::mainLoop()
  2. {
  3. if (_purgeDirectorInNextLoop)
  4. {
  5. _purgeDirectorInNextLoop = false;
  6. purgeDirector();
  7. }
  8. else if (_restartDirectorInNextLoop)
  9. {
  10. _restartDirectorInNextLoop = false;
  11. restartDirector();
  12. }
  13. else if (! _invalid)
  14. {
  15. drawScene();
  16. // release the objects
  17. PoolManager::getInstance()->getCurrentPool()->clear();
  18. }
  19. }

  1. void AutoreleasePool::clear()
  2. {
  3. #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
  4. _isClearing = true;
  5. #endif
  6. std::vector<Ref*> releasings;
  7. releasings.swap(_managedObjectArray);
  8. for (const auto &obj : releasings)
  9. {
  10. obj->release();
  11. }
  12. #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
  13. _isClearing = false;
  14. #endif
  15. }

调用releasings.swap(_managedObjectArray)后当前自动内存池中就被清空了。
  1. for (const auto &obj : releasings)
  2. {
  3. obj->release();
  4. }
创建一个对象时,该对象的引用计数被初始化为1,如果我们没有对该对象进行retain操作,或者没有使用它(也就是没有其它对象引用它),那么该对象的引用计数则为1,调用上面的代码后,该对象的引用计数变为0,之后便不复存在。

结论:

自动内存池只作用于创建期的对象,也就是刚用create函数创建的对象。如果我们没有使用它,或者没有进行retain操作,那它下一帧就会被清除。

猜你在找的Cocos2d-x相关文章