Привет, Хабр! Представляю вашем вниманию перевод моей статьи "Convenient pointer for objects of Cocos2d-x"
Все объекты cocos2d-x унаследованы от класса Ref. Этот класс содержит счетчик ссылок в переменной _referenceCount. Мы должны использовать функции release() и reatain() для того чтобы управлять этим счетчиком. Но это может создать много проблем. Например, программист может забыть вызвать release() в деструкторе объекта. Как результат, мы получим утечки памяти. Чтобы избежать этой проблемы и облегчить работу с объектами cocos2d-x, я написал маленький шаблон указателя на объект кокоса. Это не shared указатель и мы также не можем созадть weak указатель для объектов кокоса. Но этот шаблон удобен для использования.
Как это использовать?
Теперь вам не надо заботиться о вызове retain() и release(). А как вы решаете эту проблему?
Все объекты 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(). А как вы решаете эту проблему?