cocos2dx系列之Ref类
cocos2dx引擎系列之-------Ref
类
在cocos2dx引擎中,经常可以看到这个'Ref'类,但是他到底是什么?
到底他是怎么一回事呢,下面呢,就来好好的深究一下这个Ref
到底在做什么
首先来到Ref的类下:
class CC_DLL Ref
{
public:
void retain();
void release();
Ref* autorelease();
unsigned int getReferenceCount() const;
protected:
Ref();
public:
virtual ~Ref();
protected:
unsigned int _referenceCount;
friend class AutoreleasePool;
#if CC_ENABLE_SCRIPT_BINDING
public:
unsigned int _ID;
int _luaID;
void* _scriptObject;
#endif
#if CC_REF_LEAK_DETECTION
public:
static void printLeaks();
#endif
};
该类的几个成员都在这个,首先开看下,第一个函数,先从他的构造器,也就是构造函数开始看起Ref()
;
不难发现,首先Ref()
;这个构造函数是受保护的成员,他的属性是protected
,那么这就说明了一个问题
说明Ref函数是不能被实例化的,说的通俗点是不能被new的,这就表示说,它只能被继承,被使用。
然后看下他的实现:
Ref::Ref()
: _referenceCount(1)
{
#if CC_ENABLE_SCRIPT_BINDING
static unsigned int uObjectCount = 0;
_luaID = 0;
_ID = ++uObjectCount;
_scriptObject = nullptr;
#endif
#if CC_REF_LEAK_DETECTION
trackRef(this);
#endif
}
在他的构造函数列表中将他的成员_referenceCount
初始化为1了,而它的这个_referenceCount
成员又表示什么呢?
接着往下看。
void retain();
retain
字面意思就是说保留的意思,那么这个函数又与保留有什么关系呢。看实现:
void Ref::retain()
{
CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
++_referenceCount;
}
可以看出来,做的操作很简单,就是将_referenceCount
这个成员自加1。至于_referenceCount
到底做什么用,好想看到这并没有
多大的眉目,再往下看。
void release();
release
?难道是释放?看实现:
void Ref::release()
{
CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
--_referenceCount;
if (_referenceCount == 0)
{
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
auto poolManager = PoolManager::getInstance();
if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this))
{
// Trigger an assert if the reference count is 0 but the Ref is still in autorelease pool.
// This happens when 'autorelease/release' were not used in pairs with 'new/retain'.
//
// Wrong usage (1):
//
// auto obj = Node::create(); // Ref = 1, but it's an autorelease Ref which means it was in the autorelease pool.
// obj->autorelease(); // Wrong: If you wish to invoke autorelease several times, you should retain `obj` first.
//
// Wrong usage (2):
//
// auto obj = Node::create();
// obj->release(); // Wrong: obj is an autorelease Ref, it will be released when clearing current pool.
//
// Correct usage (1):
//
// auto obj = Node::create();
// |- new Node(); // `new` is the pair of the `autorelease` of next line
// |- autorelease(); // The pair of `new Node`.
//
// obj->retain();
// obj->autorelease(); // This `autorelease` is the pair of `retain` of previous line.
//
// Correct usage (2):
//
// auto obj = Node::create();
// obj->retain();
// obj->release(); // This `release` is the pair of `retain` of previous line.
CCASSERT(false, "The reference shouldn't be 0 because it is still in autorelease pool.");
}
#endif
#if CC_REF_LEAK_DETECTION
untrackRef(this);
#endif
delete this;
}
}
中间一大段的注释那是debug是用的,你可以打开然后debug看它怎么执行的,所以在这里笔者就不追究了,反正能看到--_referenceCount
;
它是将这个成员变量_referenceCount
自减一,接下来再往下看,if (_referenceCount == 0)
这个判断语句,然后还有一句delete this
;看到这,估计大家都应该明了了,其实,这里就是引擎的计数管理机制,而这个_referenceCount
就是在计数,每创建出来之后一个对象之后
就将这个对象的_referenceCount
的数值置为1,当调用retain
函数的时候,就将这个对象的_referenceCount
自加1.当调用release
的时候就会将这个_referenceCount
自减一。
接下来看看他的析构函数:
Ref::~Ref()
{
#if CC_ENABLE_SCRIPT_BINDING
if (_luaID)
{
ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptObjectByObject(this);
}
else
{
ScriptEngineProtocol* pEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (pEngine != nullptr && pEngine->getScriptType() == kScriptTypeJavascript)
{
pEngine->removeScriptObjectByObject(this);
}
}
#endif
#if CC_REF_LEAK_DETECTION
if (_referenceCount != 0)
untrackRef(this);
#endif
}
在这里,笔者就不多说了,这个西沟提供的是lua和js的调用接口和方法,也就没什么说的了。再最后来看这个重头戏autorelease()
,废话不多说,先看实现:
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
就一句话,PoolManager::getInstance()->getCurrentPool()->addObject(this)
;那么这句话啥意思呢?PoolManager
又是什么角色呢?这个咱们放到下期再说,关于cocos2dx的内存池和内存管理者!!!谢谢!!
纯手打,忘支持!!!!!!
>>> 本文链接:http://www.mayflygeek.com/archives/106/
>>> 欢迎转载。转载请注明:转载自蜉蝣极客:《cocos2dx系列之Ref类》