浅谈自己对cocos2dx的内存管理的理解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈自己对cocos2dx的内存管理的理解相关的知识,希望对你有一定的参考价值。
拿个自己写Layer的例子
1 auto genMenuWnd = GeneralMenuWnd::create(); 2 CC_BREAK_IF(!genMenuWnd); 3 addChild(genMenuWnd, 100);
该引用计数变化流程
GeneralMenuWnd在create()的时候,其_referenceCount 为1,并在create()的时候autorelease();
addChild()的时候,其_referenceCount变为2;
当该帧执行完后,_referenceCount变为1;
genMenuWnd析构时,_referenceCount变为0, 删除;
大体是这样子的:
GeneralMenuWnd继承Ref,Ref的构造函数:
1 Ref::Ref() 2 : _referenceCount(1) // when the Ref is created, the reference count of it is 1 其引用计数默认为1 3 #if CC_ENABLE_SCRIPT_BINDING 4 , _luaID (0) 5 , _scriptObject(nullptr) 6 , _rooted(false) 7 , _scriptOwned(false) 8 ,_referenceCountAtRootTime(0) 9 #endif 10 { 11 #if CC_ENABLE_SCRIPT_BINDING 12 static unsigned int uObjectCount = 0; 13 _ID = ++uObjectCount; 14 #endif 15 16 #if CC_REF_LEAK_DETECTION 17 trackRef(this); 18 #endif 19 }
在GeneralMenuWnd::create()中会调用autorelease(); 此时genMenuWnd会被放在AutoreleasePool里面.
1 Ref* Ref::autorelease() 2 { 3 PoolManager::getInstance()->getCurrentPool()->addObject(this); 4 return this; 5 }
执行addChild(), 流程addChild() ---> addChildHelper() ---> insertChild()
1 void Node::addChild(Node* child, int localZOrder, const std::string &name) 2 { 3 CCASSERT(child != nullptr, "Argument must be non-nil"); 4 CCASSERT(child->_parent == nullptr, "child already added. It can‘t be added again"); 5 6 addChildHelper(child, localZOrder, INVALID_TAG, name, false); //第一步 7 } 8 9 void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::string &name, bool setTag) 10 { 11 if (_children.empty()) 12 { 13 this->childrenAlloc(); 14 } 15 16 this->insertChild(child, localZOrder); //第二步 17 18 if (setTag) 19 child->setTag(tag); 20 else 21 child->setName(name); 22 23 child->setParent(this); 24 child->setOrderOfArrival(s_globalOrderOfArrival++); 25 26 if( _running ) 27 { 28 child->onEnter(); 29 // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter 30 if (_isTransitionFinished) 31 { 32 child->onEnterTransitionDidFinish(); 33 } 34 } 35 36 if (_cascadeColorEnabled) 37 { 38 updateCascadeColor(); 39 } 40 41 if (_cascadeOpacityEnabled) 42 { 43 updateCascadeOpacity(); 44 } 45 }
1 // helper used by reorderChild & add 2 void Node::insertChild(Node* child, int z) 3 { 4 _transformUpdated = true; 5 _reorderChildDirty = true; 6 _children.pushBack(child); //第三步 7 child->_localZOrder = z; 8 }
_children是一个Vector容器(cocos2dx自己封装过的)它在pushBack的时候是这个样子
1 void pushBack(T object) 2 { 3 CCASSERT(object != nullptr, "The object should not be nullptr"); 4 _data.push_back( object ); 5 object->retain(); //在这里, 引用计数被加1 6 }
执行完addChild()之后,其引用计数为2
在当前帧执行完成时:
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 17 // release the objects 18 PoolManager::getInstance()->getCurrentPool()->clear();//在这里会清空自动释放池中的所有单位,即其引用计数-1 19 } 20 }
所以这个时候其引用计数为1。
在genMenuWnd析构的时候,会释放_children,此时调用Vector()的clear()
1 void clear() 2 { 3 for( auto it = std::begin(_data); it != std::end(_data); ++it ) { 4 (*it)->release(); 5 } 6 _data.clear(); 7 }
所以该节点的引用计数变为了0,此时会进行delete
以上是关于浅谈自己对cocos2dx的内存管理的理解的主要内容,如果未能解决你的问题,请参考以下文章