cocos2dx内存管理机制学习笔记,源码分析
2017-11-08 11:12
639 查看
cocos2dx面试时最容易考的问题就是内存管理,我自己都被问的烦了,本文分析透彻,源码详尽,可以避免在这个问题上失分
cocos2dx的内存管理采用引用计数的策略,百度百科的引用计数解释如下:
通过源代码分析,作出以下总结:
1.Ref类中的_referenceCount成员变量用作引用计数
2.Ref的构造函数为_referenceCount赋值为1
3.retain() 执行++_referenceCount,release()执行--_referenceCount,并且当_referenceCount ==0时,释放对象.
4.autorelease()会在自动释放池中,添加一个对象(向量尾部插入新对象),AutoreleasePool类中,使用向量容器vector<Ref*> _managedObjectArray保存对象。
6.导演类的mainLoop()执行drawScene()画完一帧后,执行 PoolManager::getInstance()->getCurrentPool()->clear();clear()有2个功能:
(1)
用新向量releasings和向量_managectArray互换,将_managedObjectArray内容清空,长度清0,这么做是为了让自动释放池中的对象只自动执行一次release()判断是否释放
(2)
遍历自动释放池中的对象逐一调用一次release(),完整代码如下:
8.当对象的指针作为形参时,函数体内需retain()形参 (形参被其他指针保留了,所以需retain),
release被赋值指针(被赋值指针不需要使用原先指向的对象了,所以需release),再赋值.
cocos2dx的内存管理采用引用计数的策略,百度百科的引用计数解释如下:
通过源代码分析,作出以下总结:
1.Ref类中的_referenceCount成员变量用作引用计数
protected: /// count of references unsigned int _referenceCount;
2.Ref的构造函数为_referenceCount赋值为1
Ref::Ref() : _referenceCount(1) // when the Ref is created, the reference count of it is 1
3.retain() 执行++_referenceCount,release()执行--_referenceCount,并且当_referenceCount ==0时,释放对象.
void Ref::retain() { ++_referenceCount; } void Ref::release() { --_referenceCount; if (_referenceCount == 0) { delete this; } }
4.autorelease()会在自动释放池中,添加一个对象(向量尾部插入新对象),AutoreleasePool类中,使用向量容器vector<Ref*> _managedObjectArray保存对象。
Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addObject(this); return this; } void AutoreleasePool::addObject(Ref* object) { _managedObjectArray.push_back(object); } std::vector<Ref*> _managedObjectArray;5.通过create()创建的对象,会执行new(),init(),autorelease()几个函数,即对象被放入自动释放池,这类对象若不addchild()会在下一帧释放,若想保留可手动retain(),不需要时手动release()
Scene* Scene::create() { Scene *ret = new (std::nothrow) Scene(); if (ret && ret->init()) { ret->autorelease(); return ret; } else { CC_SAFE_DELETE(ret); return nullptr; } }
6.导演类的mainLoop()执行drawScene()画完一帧后,执行 PoolManager::getInstance()->getCurrentPool()->clear();clear()有2个功能:
(1)
std::vector<Ref*> releasings; releasings.swap(_managedObjectArray);
用新向量releasings和向量_managectArray互换,将_managedObjectArray内容清空,长度清0,这么做是为了让自动释放池中的对象只自动执行一次release()判断是否释放
(2)
for (const auto &obj : releasings) { obj->release(); }
遍历自动释放池中的对象逐一调用一次release(),完整代码如下:
void DisplayLinkDirector::mainLoop()7.addChild(Node *child)会执行child->retain();removechild()会执行child->release();
{
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
}
void Node::addChild(Node *child) { CCASSERT( child != nullptr, "Argument must be non-nil"); this->addChild(child, child->_localZOrder, child->_name); } void Node::addChild(Node* child, int localZOrder, const std::string &name) { CCASSERT(child != nullptr, "Argument must be non-nil"); CCASSERT(child->_parent == nullptr, "child already added. It can't be added again"); addChildHelper(child, localZOrder, INVALID_TAG, name, false); } void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::string &name, bool setTag) { if (_children.empty()) { this->childrenAlloc(); } this->insertChild(child, localZOrder); //以下省略 } void Node::insertChild(Node* child, int z) { _transformUpdated = true; _reorderChildDirty = true; _children.pushBack(child); child->_localZOrder = z; } void pushBack(T object) { CCASSERT(object != nullptr, "The object should not be nullptr"); _data.push_back( object ); object->retain(); }
8.当对象的指针作为形参时,函数体内需retain()形参 (形参被其他指针保留了,所以需retain),
release被赋值指针(被赋值指针不需要使用原先指向的对象了,所以需release),再赋值.
void testFun(Ref* obj1) { obj1->retain(); obj2->release(); obj2 = obj1; }
相关文章推荐
- nginx 源码学习笔记(七)——内存分配相关源码分析
- C++ Standard Stl -- SGI STL源码学习笔记(04) stl_deque && 初涉STL内存管理
- 【Cocos2d-x 3.x】内存管理机制与源码分析
- nginx 源码学习笔记(七)——内存分配相关源码分析
- 深入理解JVM学习笔记-自动内存管理机制
- Cocos2dx 学习(一) 内存管理机制
- COCOS2DX 3.0 学习笔记:从源码分析Cocos2dx 3.0 Director类
- java虚拟机学习笔记_第一部分内存管理机制
- memcached源码学习-内存管理机制slab allocator
- nginx 源码学习笔记(七)——内存分配相关源码分析
- Java 学习笔记 (13) - 基本内存分析 和 垃圾回收机制
- cocos2d-x源码分析::内存管理机制
- 学习笔记:Objective C 的内存管理(4)----ARC内存管理机制
- zz : memcached源码学习-内存管理机制slab allocator
- Nginx源码分析(2)之——共享内存管理之slab机制
- cocos2dx 3.x 自学笔记 <三> cocos2dx 2.x 3.x 内存管理机制
- cocos2dx 学习(-)内存管理机制
- Python源码分析--学习笔记一
- Ogre源码分析与学习笔记-1
- Ogre源码分析与学习笔记-0