cocos2dx - 节点管理
接上一节内容:cocos2dx - v2.3.3编辑器骨骼动画
本节主要Cocos2dx中节点的管理及应用
一般用法
用过Cocos2dx应该都有用过addChild,removeChild方法。或者retain,release方法。
addChild,removeChild方法都是继承Node类,retain,release方法则继承自Ref类。
查看cocos2dx库代码可以看到,Ref中retain,release主要维持了一个_referenceCount计数变量
通过retain方法可以使_referenceCount计数加1,同时release可以使_referenceCount计数减1,并且在_referenceCount计数为0时,释放对象。
void Ref::retain()
{
CCASSERT(_referenceCount > , "reference count should be greater than 0");
++_referenceCount;
} void Ref::release()
{
CCASSERT(_referenceCount > , "reference count should be greater than 0");
--_referenceCount; if (_referenceCount == )
{
delete this;
}
}
查看Node的实现也可以了解Node中维护了一个CCVector对象来存储子节点,在erase子节点时,对子节点调用release方法,同时在pushBack新节点时,对子节点调用retain方法。
下面是CCVector中pushBack及erase的一些细节:
// Adds objects
/** Adds a new element at the end of the Vector. */
void pushBack(T object)
{
CCASSERT(object != nullptr, "The object should not be nullptr");
_data.push_back( object );
object->retain();
}
/** @brief Removes from the vector with an iterator.
* @param position Iterator pointing to a single element to be removed from the Vector.
* @return An iterator pointing to the new location of the element that followed the last element erased by the function call.
* This is the container end if the operation erased the last element in the sequence.
*/
iterator erase(iterator position)
{
CCASSERT(position >= _data.begin() && position < _data.end(), "Invalid position!");
(*position)->release();
return _data.erase(position);
}
这样就说明了Node节点实际还是在对Ref继承的_referenceCount进行计数处理。
若Node没有添加到父节点中,那么_referenceCount什么时候变成0,又什么时候释放节点的?
首先在Ref的构造函数中,可以看到_referenceCount初始化为1
Ref::Ref()
: _referenceCount() // when the Ref is created, the reference count of it is 1
{
#if CC_ENABLE_SCRIPT_BINDING
static unsigned int uObjectCount = ;
_luaID = ;
_ID = ++uObjectCount;
_scriptObject = nullptr;
#endif #if CC_REF_LEAK_DETECTION
trackRef(this);
#endif
}
同时,在Node的静态创建方法Node::create中,宏定义 CREATE_FUNC(Node) 实现如下,
/** @def CREATE_FUNC(__TYPE__)
* Define a create function for a specific type, such as Layer.
*
* @param __TYPE__ class type to add create(), such as Layer.
*/
#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 = nullptr; \
return nullptr; \
} \
}
可以看到,在对象创建失败会直接delete,并返回nullptr。创建成功则调用了autorelease方法,如下:
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
说明在正常创建Node节点时,会将其添加到coco2dx的一个内存池进行管理。同时在主循环中看到,下一帧处理对当前内存池对象进行了一次清理,并调用了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
}
因此,如果一个对象在创建后,没有及时进行retain或者添加到父节点中,在当前帧结束时被调用release方法导致 _referenceCount变成0,从而被释放。
几个示例:
Scene* pScene = Director::getInstance()->getRunningScene();
if (pScene)
{
Node* pNode1 =Node::create(); // pNode1创建后没有处理,在当前帧结束前被释放 Node* pNode2 =Node::create(); // pNode2创建后添加到场景中,不会被释放
pScene->addChild(pNode2); Node* pNode3 =pScene->getChildByTag();
if(pNode3)
{
pScene->removeChild(pNode3); // pNode3被立即释放
pNode2->addChild(pNode3); // 错误!! pNode3已被释放
} Node* pNode4 =Node::create();
pNode2->addChild(pNode4); // pNode4 随 pNode2释放 Node* pNode5 =Node::create();
pScene->addChild(pNode5);
pNode5->retain();
pScene->removeChild(pNode5);
pNode2->addChild(pNode5);
pNode5->release(); // pNode5 随 pNode2释放 }
cocos2dx - 节点管理的更多相关文章
- 2、COCOS2D-X内存管理机制
在C++中.动态内存分配是一把双刃剑,一方面,直接訪问内存地址提高了应用程序的性能,与使用内存的灵活性.还有一方面.因为程序没有正确地分配与释放造成的比如野指针,反复释放,内存泄漏等问题又严重影响着应 ...
- cocos2d-x内存管理
Cocos2d-x内存管理 老师让我给班上同学讲讲cocos2d-x的内存管理,时间也不多,于是看了看源码,写了个提纲和大概思想 一. 为什么需要内存管理 1. new和delete 2. 堆上申 ...
- 在控制台启动服务器时出现:对于服务器soa1_wls, 与计算机oim1相关联的节点管理器无法访问。
问题:在控制台启动服务器时出现:对于服务器soa1_wls, 与计算机oim1相关联的节点管理器无法访问.原因:nodemanager没有启起来解决方法: 一.对于managedServer于admi ...
- [转] Jenkins实战演练之Windows系统节点管理
[前提] 通过<Jenkins实战演练之Windows服务器快速搭建>(http://my.oschina.net/iware/blog /191818)和<Jenkins实战演练之 ...
- 转:对于服务器AdminServer, 与计算机Machine-0相关联的节点管理器无法访问
控制台启动server时报"对于服务器server-1与计算机machin<!--StartFragment -->对于服务器AdminServer, 与计算机Machine-0 ...
- 20151208_使用windows2012配置weblogic节点管理器
经过实践,weblogic节点管理器的作用主要有两点: 1.可通过weblogic控制台远程控制被管server启停. 2.可以自动重启被管server的进程,并且对spring框架提供比直接启动更快 ...
- weblogic11g 节点管理器 nodemanager
Weblogic 节点管理器 nodemanager 一.Weblogic 规划 : Server名称 端口 ip 备注 xyyadmin 7001 10.10.54.74 管理server ap ...
- cocos2dx内存管理的一些看法
今年年初进入一家游戏公司,正式开始游戏引擎的学习,之前的ios学习,对现在的游戏引擎学习还是有很大的帮助的,虽然使用c++,但却能时刻感受到ios框架对于cocos2dx的巨大影响. 由于之前一直使用 ...
- Cocos2d-x内存管理解说在ios开发中
使用过 Cocos2d-x 都知道,其中有一套自己实现的内存管理机制,不同于一般 C++ 的编写常规,而在使用前,了解其原理是有必要的,网上已经有很多对内部实现详细解说的文章.而对于使用者而言,并不需 ...
随机推荐
- 团队作业4——第一次项目冲刺(Alpha版本)第一天+第二天+第三天+第四天+第五天+第六天+第七天
冲刺第一天 一.Daily Scrum Meeting照片 二.每个人的工作 1.今天计划完成的任务 GUI.计时功能.题目生成 2.工作中遇到的困难 刚开始在计时功能模块只能做到秒位,经过查询资料后 ...
- 201521123111《Java程序设计》第5周学习总结
1. 本章学习总结 你对于本章知识的学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 2. 书面作业 1.代码阅读:Child压缩包内源代码 ...
- thinkphp创建对象及数据操作
ThinkPHP有三种创建控制器对象的方式: 通过命名空间的路径找到类然后new出来例如:$dx = new \Home\Controller\IndexController(); 通过A快捷函数创建 ...
- 利用Vim提供的正则去掉代码每行开头不想要的行号以及vi常见问题和应用技巧
看到一不错的代码片断,但奈何无论怎么拷贝,粘贴到VS里都是带行号的,300多行的代码手工删除行号与前面的空格可得耗不少时间...这时想起了无所不能的VIM,以及它的正则,它的替换功能.解决步骤: 1. ...
- Lucene第一篇【介绍Lucene、快速入门】
什么是Lucene?? Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引 ...
- Eclipse读取含有extjs的项目文件时卡死或者编写ExtJS时卡
新建一个Eclipse或MyEclipse项目时,关掉验证. 项目右键-->Properties-->Builders--> 不勾选(JavaScript Validator.Val ...
- Linux Ubuntu从零开始部署web环境及项目-----搭建ssh环境(一)
linux搭建ssh环境 1,用户登录 成功输入用户名和密码后 进入Ubuntu界面 2,配置网络 参考:http://blog.csdn.net/liu782726344/article/deta ...
- PHP数组运算符
PHP数组预算符有==(等于),===(恒等于),!=(不等于),<>(不等于),+(联合): 注意:没有-(减号)运算符: $a=array("a"=>&quo ...
- Python 接口测试(四)
五:python数列化和反序列化 把python的对象编码转换为json格式的字符串,反序列化可以理解为:把json格式 字符串解码为python数据对象.在python的标准库中,专门提供了json ...
- [转载]iOS开发之手势识别
感觉有必要把iOS开发中的手势识别做一个小小的总结.在上一篇iOS开发之自定义表情键盘(组件封装与自动布局)博客中用到了一个轻击手势,就是在轻击TextView时从表情键盘回到系统键盘,在TextVi ...