cocos2dx系列之Ref类

发表于2015-08-14
评论0 1.3k浏览
 

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类》

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引