8、Cocos2dx 3.0三,找一个小游戏开发3.0存储器管理的版本号
3.0实现了新的根类Ref。 引擎中的全部类都派生自Ref。
/** Interface that defines how to clone an Ref */
class CC_DLL Clonable
{
public:
/** returns a copy of the Ref */
virtual Clonable* clone() const = 0;
/**
* @js NA
* @lua NA
*/
virtual ~Clonable() {}; /** returns a copy of the Ref.
@deprecated Use clone() instead
*/
CC_DEPRECATED_ATTRIBUTE Ref* copy() const
{
// use "clone" instead
CC_ASSERT(false);
return nullptr;
}
}; class CC_DLL Ref
{
public:
void retain(); void release(); Ref* autorelease(); unsigned int getReferenceCount() const; protected:
Ref(); public:
virtual ~Ref(); protected:
/// count of references
unsigned int _referenceCount; friend class AutoreleasePool; #if CC_ENABLE_SCRIPT_BINDING
public:
/// object id, ScriptSupport need public _ID
unsigned int _ID;
/// Lua reference id
int _luaID;
#endif
};
Clonable类:定义如何复制Ref类的接口
virtual Clonable *clone() const =0; //克隆函数是纯虚函数,必须在子类重写
例:
virtual __Array *clone() const;
实现:
__Array* __Array::clone() const
{
__Array* ret = new __Array();
ret->autorelease();
ret->initWithCapacity(this->data->num > 0 ? this->data->num : 1);
return ret;
}
void retain(); //保持全部权,添加Ref的引用次数
void release(); //降低引用次数,引用计数直接减一,假设引用次数等于0。马上释放
Ref* autorelease(); //自己主动释放。将该物体增加自己主动释放池。当引用计数为0时自己主动释放
举个错误使用样例:
auto obj=Node::create(); //Ref=1,可是当前Node已经在自己主动释放缓冲池中
obj->autorelease(); //错误:假设你调用autorelease()非常多次,你必须retain()
从源代码中能够看到,每一个对象包括一个用来控制生命周期的引用计数器,它就是 Ref的成员变量_referenceCount。
我们能够通过 getReferenceCount()方法获得对象当前的引用计数值。
在对象通过构造函数创建的时候,该引用值被赋为 1,表示对象由创建者所引用。
在其它地方须要引用对象时,我们会调用 retain()方法,令其引用计数增 1,表示获取该对象的引用权;
在引用 结束的时候调用 release()方法,令其引用计数值减 1,表示释放该对象的引用权。
相对于IOS SDK把这个内存计数封装到了NSAutoreleasePool中。
在cocos2d-x相同有一套CCAutoreleasePool与之相相应。
两者的使用方法基本一样。
这就要讲到这个非常有意思的方法:autorelease()。
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
其作用是将对象放入自己主动回收池(AutoreleasePool)。
AutoreleasePool::~AutoreleasePool()
{
CCLOGINFO("deallocing AutoreleasePool: %p", this);
clear(); PoolManager::getInstance()->pop();
}
当回收池自身被释放 的时候。 它就会对池中的全部对象运行一次 release()方法, 实现灵活的垃圾回收。
回收池能够手动创建和释放。
除此之外。 引擎在每次游戏循环開始之前也会创建一个回收池,在循环结束后释放回收池。
因此,即使我们没有手工创建和释放回收 池,每一帧结束的时候,
自己主动回收池中的对象也都会被运行一次 release()方法。
我们立即就会领略到 autorelease()的方 便之处。
以下是一个简单的样例。
能够看到。对象创建后,引用计数为 1;
运行一次 retain()后,引用计数为 2。
运行一次 release()后,引用计数回到 1;
运行一次 autorelease()后,对象的引用计数值并没有马上减 1,可是在下一帧開始前,对象会被释放掉。
以下是測试代码:
mistress = new CCSprite();
mistress->init();
CCLog("retainCount after init: %d", mistress->getReferenceCount());
mistress->retain();
CCLog("retainCount after retain: %d", mistress->getReferenceCount());
mistress->release();
CCLog("retainCount after release: %d", mistress->getReferenceCount());
mistress->autorelease();
CCLog("retainCount after autorelease: %d", mistress->getReferenceCount());
控制台显示的日志例如以下:
Cocos2d: retainCount after init: 1
Cocos2d: retainCount after retain: 2
Cocos2d: retainCount after release: 1
Cocos2d: retainCount after autorelease: 1
我们已经知道,调用了 autorelease()方法的对象,将会在自己主动回收池释放的时候被释放一次。
尽管。Cocos2d-x 已经保证每一帧结束后释放一次回收池,并在下一帧開始前创建一个新的回收池。可是我们也应该
考虑到回收池本身维护着一个将要运行释放操作的对象列表。假设在一帧之内生成了大量的 autorelease 对象,将会导致回收池性能下降。
因此,在生成 autorelease 对象密集的区域(一般是循环中)的前后,我们最好能够手动创建并释放一个回收池。
我们能够通过回收池管理器 PoolManager的 push()或 pop()方法来创建或释放回收池。当中的 PoolManager 也是一个单例对象。能够通过PoolManager::getInstance()获取该单例对象。
在这里,再通过段简单的代码来分析自己主动回收池的嵌套机制:
PoolManager::getInstance()->push(this);
for(int i=0; i<n; i++)
{
String* dataItem = String::createWithFormat("%d", Data[i]);
stringVector->push_back(dataItem);
}
PoolManager::getInstance()->pop();
这段代码包括了一个运行 n 次的循环,每次都会创建一个 autorelease 对象 String。
为了保持回收池的性能,我们在循环前使用 push()方法创建了一个新的回收池。在循环结束后使用 pop()方法释放刚才创建的回收池。
不难看出,自己主动回收池是可嵌套的。
通常,引擎维护着一个回收池。全部的 autorelease 对象都加入到了这个池中。
多个自己主动回收池排列成栈结构,当我们手动创建了回收池后,回收池会压入栈的顶端。autorelease 对象仅加入到顶端的池中。当顶层的回收池被弹出释放时,
它内部全部的对象都会被释放一次, 此后出现的 autorelease 对象则会加入到下一个池中。
在自己主动回收池嵌套的情况下,每个对象是怎样增加自己主动回收池以及怎样释放的。相关代码例如以下所看到的:
//步骤 a
obj1->autorelease();
obj2->autorelease(); //步骤 b
PoolManager::getInstance()->push(this); //步骤 c
for(int i=0; i<n; i++) {
obj_array[i]->autorelease();
}
//步骤 d
PoolManager::getInstance()->pop();
//步骤 e
obj3->autorelease();
上述代码的详细过程如图所看到的:
当运行完步骤 a 时,obj1 与 obj2 被增加到回收池 1 中。如图 a 所看到的;
步骤 b 创建了一个新的回收池。此时回收池 2 接管全部 autorelease 操作,如图b 所看到的。
步骤 c 是一个循环。当中把 n 个对象增加回收池 2 中,如图c 所看到的。
步骤 d 释放了回收池 2,因此回收池 2 中的 n 个对象都被释放了一次,同一时候回收池 1 接管autorelease 操作;
步骤 e 调用 obj3 的 autorelease()方法,把 obj3 增加回收池 1 中。如图e 所看到的。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGFuaWVsenp1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
版权声明:本文博客原创文章,博客,未经同意,不得转载。
8、Cocos2dx 3.0三,找一个小游戏开发3.0存储器管理的版本号的更多相关文章
- 13、Cocos2dx 3.0三,找一个小游戏开发3.0中间Director :郝梦主,一统江湖
重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27706967 游戏中的基本元素 在曾经文章中,我们具 ...
- 14、Cocos2dx 3.0三,找一个小游戏开发Scene and Layer:游戏梦想
发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/30474393 Scene :场景 了解了Director ...
- 4、Cocos2dx 3.0三,找一个小游戏开发Hello World 分析
尊重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27186557 Hello World 分析 打开新 ...
- 三、微信小游戏开发 --- 小游戏API调用Platform
微信小游戏API Platform主要是Egret用于来调用平台的SDK的. 在Egret中使用接口定义Platform. Egret项目中默认的platform值是DebugPlatform. 发布 ...
- linux下开发,解决cocos2d-x中编译出现的一个小问题, undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'
解决cocos2d-x中编译出现的一个小问题 对于cocos2d-x 2.×中编译中,若头文件里引入了#include "cocos-ext.h",在进行C++编译的时候会遇到例如 ...
- Pygame:编写一个小游戏 标签: pythonpygame游戏 2017-06-20 15:06 103人阅读 评论(0)
大学最后的考试终于结束了,迎来了暑假和大四的漫长的"自由"假期.当然要自己好好"玩玩"了. 我最近在学习Python,本意是在机器学习深度学习上使用Python ...
- 使用PixiJS做一个小游戏
PixiJS PixiJS使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库. 官方 ...
- DirectX游戏开发——从一个小游戏開始
本系列文章由birdlove1987编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/26364129 写在前面:自 ...
- Egret白鹭H5小游戏开发入门(三)
前言: 在上一篇文章中着重介绍了H5小游戏开发的起步阶段,如Wing面板的使用,素材的处理,类的说明等等,那么今天主要是涉及到场景的创建,loading的修改等等的代码编写. 对于这一节,我在讲解的过 ...
随机推荐
- 用XAML做网页!!—框架
原文:用XAML做网页!!-框架 上一篇中我进行了一下效果展示和概述,此篇开始将重现我此次尝试的步骤,我想大家通过阅读这些步骤,可以了解到XAML网页排版的方法. 下面就开始编写XAML,首先来定义一 ...
- 如何用C#使用java
如何使用C#调用Java 今天需要使用C#调用Java的包,研究了一下,大体是以下几种解决方案: 把Java包转换为DLL或者EXE后注册为com组件,之后调用. 使用web service 比如:H ...
- HttpClient4的使用,模拟浏览器登陆新浪微博,发表微博和文字+图片微博
HttpClient4,最原始的需求就是使用其来模拟浏览器想服务器发起http请求,当然,他的功能不止于此,但是我需要的就是这个功能而已,jdk也有其自带的类似的api:UrlConnection,效 ...
- 讨论asp.net通过机器cookie仿百度(google)实现搜索input搜索提示弹出框自己主动
为实现自己主动弹出通过用户输入关键词相关的搜索结果,在这里,我举两个解决方案,对于两个不同的方案. 常用的方法是建立一个用户数据库中查找关系表.然后输入用户搜索框keyword异步调用数据表中的相关数 ...
- windows phone 独立存储空间的操作 (2)
原文:windows phone 独立存储空间的操作 (2) IsolatedStorage独立存储空间是保存应用程序的一些数据已经配置文件,独立存储空间相对于其他的wp程序是独立的,也就是说每个wp ...
- BZOJ 1449 JSOI2009 球队收益 费用流
题目大意:给定nn支球队.第ii支球队已经赢了winiwin_i场.输了loseilose_i场,接下来还有mm场比赛.每一个球队终于的收益为Ci∗x2i+Di∗y2iC_i*x_i^2+D_i*y_ ...
- 一起学习android图片四舍五入图片集资源 (28)
效果图: 參看下面代码: public class MainActivity extends Activity { private ImageView imageView1; private Imag ...
- C# 视频教程
http://www.cnblogs.com/kellen/tag/Silverlight/ http://www.lanmaodream.com/archives/244.html
- SharePoint 2010 新列表模板列表
SharePoint 2010 新列表模板列表 项目描述叙事 发展环境创造了良好的名单为模板.然后使用列表模板将其复制到生产环境. 脚步 1. 打开"列表设置",找到"将 ...
- Directx11学习笔记【十九】 摄像机的实现
本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/p/5785100.html 之前为了方便观察场景,我们采用的方法是鼠标 ...