-
cocos内存管理是面试中问到最多的问题,也是非常重要的,如果不熟悉,可能会导致内存泄漏。
1.在cocos中内存管理主要有两个方面: 通过引用计数,在cocos中几乎所有的类都继承自Ref, Ref内部存在一个引用计数 _referenceCount, 使用retain和release来对引用计数进行操作,当引用计数为0就会释放,
-
// 引用计数变量 unsigned int _referenceCount;
// 对象被构造后,引用计数值为 1
Ref::Ref() : _referenceCount(1) {
#if CC_ENABLE_SCRIPT_BINDING
static unsigned int uObjectCount = 0;
_luaID = 0;
_ID = ++uObjectCount;
_scriptObject = nullptr;
#endif
#if CC_USE_MEM_LEAK_DETECTION
trackRef(this);
#endif
}
// 引用+1
void Ref::retain() {
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
++_referenceCount;
}
// 引用-1 。如果引用为0则释放对象
void Ref::release() {
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
--_referenceCount;
if (_referenceCount == 0) {
#if CC_USE_MEM_LEAK_DETECTION untrackRef(this);
#endif delete this; // 注意这里 把对象 delete 了
}
}
//获取引用计数值
unsigned int Ref::getReferenceCount() const {
return _referenceCount;
}
- 2.自动释放池。我们刚创建的对象,为了保证其在使用之前不会被释放,引用初始值为1,在帧过渡之时,由于是自引用,我们并不能通过其他方式访问,所有就有了自动释放池,来标记一个“创建时期对象”,统一释放“释放池引用”
PoolManager* PoolManager::getInstance() {
if (s_singleInstance == nullptr) {
s_singleInstance = new (std::nothrow) PoolManager();
// Add the first auto release pool
new (std::nothrow) AutoreleasePool("autorelease pool");
}
return s_singleInstance;
}
void AutoreleasePool::addObject(Ref* object) {
_managedObjectArray.push_back(object);
}
void AutoreleasePool::clear() {
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
_isClearing = true;
#endif
std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);
for (const auto &obj : releasings){
obj->release();
}
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
_isClearing = false;
#endif
}