cocos2dx内存管理机制学习笔记,源码分析
来源:互联网 发布:桩冠修复 知乎 编辑:程序博客网 时间:2024/06/08 11:35
cocos2dx面试时最容易考的问题就是内存管理,我自己都被问的烦了,本文分析透彻,源码详尽,可以避免在这个问题上失分
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(){ 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}7.addChild(Node *child)会执行child->retain();removechild()会执行child->release();
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;}
阅读全文
0 0
- cocos2dx内存管理机制学习笔记,源码分析
- cocos2dx学习笔记(内存管理机制)
- cocos2dx学习笔记(内存管理机制)
- cocos2dx对象内存管理机制分析
- Cocos2dx 学习(一) 内存管理机制
- cocos2dx 学习(-)内存管理机制
- Linux内存管理机制学习笔记
- JVM学习笔记-内存管理机制
- cocos2dx的内存管理机制
- cocos2dx的内存管理机制
- Cocos2dx内存管理机制
- cocos2dx的内存管理机制
- cocos2dx的内存管理机制
- cocos2dx的内存管理机制
- cocos2dx中的内存管理机制
- cocos2dx 的内存管理机制
- cocos2dx的内存管理机制
- cocos2d-x源码分析::内存管理机制
- 阿里大于短信验证码简单实现
- recv函数和send函数
- Android属性动画(PropertyAnimation)(下)
- Java
- HDU-1175-连连看
- cocos2dx内存管理机制学习笔记,源码分析
- 安卓权限详解
- 解决在IE浏览器中返回json格式的数据时提示下载办法
- 证书的应用之一 —— TCP&SSL通信实例及协议分析(下)
- Java 泛型
- shell脚本的正则表达式
- 一些常用工具
- 服务器被挂马,文件被病毒隐藏怎么恢复显示
- 我的第一个Struts2项目