Привет, Хабр! Представляю вашем вниманию перевод моей статьи "Convenient pointer for objects of Cocos2d-x"

image



Все объекты cocos2d-x унаследованы от класса Ref. Этот класс содержит счетчик ссылок в переменной _referenceCount. Мы должны использовать функции release() и reatain() для того чтобы управлять этим счетчиком. Но это может создать много проблем. Например, программист может забыть вызвать release() в деструкторе объекта. Как результат, мы получим утечки памяти. Чтобы избежать этой проблемы и облегчить работу с объектами cocos2d-x, я написал маленький шаблон указателя на объект кокоса. Это не shared указатель и мы также не можем созадть weak указатель для объектов кокоса. Но этот шаблон удобен для использования.

#ifndef CCPtr_h
#define CCPtr_h

#include <type_traits>
#include "cocos2d.h"

template < class T,
           class = typename std::enable_if<std::is_base_of<cocos2d::Ref, T>::value>::type
>

class CCPtr {
    cocos2d::Ref *m_ptr = nullptr;
public:
    CCPtr() {}
    
    CCPtr(T *obj) {
        if (m_ptr) {
            m_ptr->release();
        }
        m_ptr = obj;
        m_ptr->retain();
    }
    
    CCPtr(CCPtr<T> &obj) {
        if (m_ptr) {
            m_ptr->release();
        }
        m_ptr = obj.m_ptr;
        m_ptr->retain();
    }
    
    CCPtr(CCPtr<T>&& obj) {
        m_ptr = obj.m_ptr;
        obj.m_ptr = nullptr;
    }
    
    void operator=(T *obj) {
        if (m_ptr) {
            m_ptr->release();
        }
        m_ptr = obj;
        m_ptr->retain();
    }
    
    void operator=(CCPtr<T> &obj) {
        if (m_ptr) {
            m_ptr->release();
        }
        m_ptr = obj.m_ptr;
        m_ptr->retain();
    }
    
    void operator=(CCPtr<T>&& obj) {
        m_ptr = obj.m_ptr;
        obj.m_ptr = nullptr;
    }

    ~CCPtr() {
        if (m_ptr) {
            m_ptr->release();
        }
        m_ptr = nullptr;
    }
    
    T* get () const { return static_cast<T*>(m_ptr); }
    T* operator->() const { return static_cast<T*>(m_ptr); }
};


#endif /* CCPtr_h */


Как это использовать?

#include "CCPtr.h"

class SpriteComponent: public Component {

//…

CC_CONSTRUCTOR_ACCESS:

    SpriteComponent(const std::string& spriteName);
    
protected:
    
    CCPtr<Sprite> m_sprite;
};


SpriteComponent::SpriteComponent(const std::string& spriteName) :
    Component ()
{
    this->setName("sprite");
    m_sprite = Sprite::create(spriteName);
}


Теперь вам не надо заботиться о вызове retain() и release(). А как вы решаете эту проблему?

Комментарии (0)