cocos2dx 采用引用计数管理自己的内存:
引用计数:
引用计数就是通过给每个对象维护一个引用计数器,记录该对象当前被引用的次数。当对象增加一次引用时,计数器+1.而对象失去一次引用时,计数器-1,当引用计数器为0时。标志着该对象的生命周期结束,自动触发对象的回收释放。
为了实现引用计数器,cocos2dx实现了自己的根类ccobject。引 擎中所有类都派生自ccobject类。一下ccobject的定义
class CC_DLL Object
{
public:
/// object id, ScriptSupport need public _ID
unsigned int _ID;
/// Lua reference id
int _luaID;
protected:
/// count of references
unsigned int _reference;
/// count of autorelease
unsigned int _autoReleaseCount;
public:
/**
* Constructor
*
* The object's reference count is 1 after construction.
* @js NA
*/
Object();
/**
* @js NA
* @lua NA
*/
virtual ~Object();
/**
* Release the ownership immediately.
*
* This decrements the object's reference count.
*
* If the reference count reaches 0 after the descrement, this object is
* destructed.
*
* @see retain, autorelease
* @js NA
*/
inline void release()
{
CCASSERT(_reference > 0, "reference count should greater than 0");
--_reference;
if (_reference == 0)
delete this;
}
/**
* Retains the ownership.
*
* This increases the object's reference count.
*
* @see release, autorelease
* @js NA
*/
inline void retain()
{
CCASSERT(_reference > 0, "reference count should greater than 0");
++_reference;
}
/**
* Release the ownership sometime soon automatically.
*
* This descrements the object's reference count at the end of current
* autorelease pool block.
*
* If the reference count reaches 0 after the descrement, this object is
* destructed.
*
* @returns The object itself.
*
* @see AutoreleasePool, retain, release
* @js NA
* @lua NA
*/
Object* autorelease();
/**
* Returns a boolean value that indicates whether there is only one
* reference to the object. That is, whether the reference count is 1.
*
* @returns Whether the object's reference count is 1.
* @js NA
*/
bool isSingleReference() const;
/**
* Returns the object's current reference count.
*
* @returns The object's reference count.
* @js NA
*/
unsigned int retainCount() const;
/**
* Returns a boolean value that indicates whether this object and a given
* object are equal.
*
* @param object The object to be compared to this object.
*
* @returns True if this object and @p object are equal, otherwise false.
* @js NA
* @lua NA
*/
virtual bool isEqual(const Object* object);
/**
* @js NA
* @lua NA
*/
virtual void acceptVisitor(DataVisitor &visitor);
/**
* @js NA
* @lua NA
*/
virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
friend class AutoreleasePool;
};
通过以上代码我们可以看出cocos2dx的内存管理机制和objective-c的管理一样。都是当
_reference = 0时释放内存。
_autoReleaseCount自动释放池的引用计数
auto sprite1 = new Sprite();
sprite1->initWithSpriteFrameName("btn_adventure_normal_CN.png");//引用计数器+1
CCLOG("retaincount = %d",sprite1->retainCount());
sprite1->retain();//引用计数器+1
CCLOG("retaincount = %d",sprite1->retainCount());
sprite1->release();//引用计数器-1
CCLOG("retaincount = %d",sprite1->retainCount());
sprite1->autorelease();//只是把该sprite放入自动释放池中。引用计数器不变。等待管理器自动释放
CCLOG("retaincount = %d",sprite1->retainCount());
coco2dx 内存管理原则
1.程序段必须成对执行retain()和release()或者执行autorelease()来开始和结束对对象的引用
2.工厂方法返回前,应通过autorelease()结束对该对象的引用
3.对象传值时,应考虑到新旧对象相同的特殊情况
4.尽量使用release()而不是autorelease()来释放对象,以确保性能。
5.保存ccobject的子类对象时,应严格使用cocos2dx提供的容器。
内存管理涉及到的宏:
#define CC_SYNTHESIZE_RETAIN(varType, varName, funName) \
private: varType varName; \
public: virtual varType get##funName(void) const { return varName; } \
public: virtual void set##funName(varType var) \
{ \
if (varName != var) \
{ \
CC_SAFE_RETAIN(var); \
CC_SAFE_RELEASE(varName); \
varName = var; \
} \
}
#define CC_SAFE_DELETE(p) do { delete (p); (p) = nullptr; } while(0)
#define CC_SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = nullptr; } } while(0)
#define CC_SAFE_FREE(p) do { if(p) { free(p); (p) = nullptr; } } while(0)
#define CC_SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0)
#define CC_SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = nullptr; } } while(0)
#define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0)