- 先简单介绍一下c++的内存管理机制,分为堆、栈、自由存储区、全局/静态存储区和常量存储区。
- Object-c中的内存管理是运用了对象引用计数的方式进行管理。每个对象都会有一个retainCount,当我们retain一次的时计数就会 +1 ,当我们调用一次release时计数器就会-1,当引用计数为0是就会释放内存。
- cocos2d-x 是调用了c++来实现了Object-c中的内存管理机制,即对象引用计数的方式。
下面介绍create()方法
以HelloWorld为例,我们可以看到3.0以后的版本都是调用create()创建对象
auto scene = Scene::create();
点看create()方法,可以看见,new了一个Scene对象
Scene *ret = new (std::nothrow) Scene();
Scene类是继承了Node类,Node类继承了Ref类。查看Ref类的.h头文件,如下:
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;
//以下是脚本的引用
@H_301_97@#if CC_ENABLE_SCRIPT_BINDING
public:
unsigned int _ID;
int _luaID;
void* _scriptObject;
@H_301_97@#endif
@H_301_97@#if CC_REF_LEAK_DETECTION
public:
static void printLeaks();
@H_301_97@#endif
};
查看Ref构造函数,可以看出当创建一Ref子对象时_referenceCount则初始化为1,,然后执行retain()时,_referenceCount则加1,release()时减1,如果_referenceCount为0则delete this,即释放内存。查看autorelease()源码可以看出,是将当前的对象添加到自动管理池中进行管理管理。
Ref* Ref::autorelease()
{ //PoolManger就是管理池,他会自动的管理内存的释放
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
我们再回头看Scene类里面的create()方法,代码中并没有出现delete语句,而是用调用autorelease()来实现内存的释放。
Scene* Scene::create()
{ //先是创建子对象
Scene *ret = new (std::nothrow) Scene();
if (ret && ret->init())//初始化对象
{
ret->autorelease();//在这里调用自动的释放引用
return ret;
}
else
{
CC_SAFE_DELETE(ret);
return nullptr;
}
}
总结:cocos2dx在创建对象时如果是Ref的子类的对象,最好是调用create()函数进行创建,这样可以省去对内存释放的手动管理,交给内存管理池让他帮助你管理,如果不是Ref的子类的对象,那就要手动的释放同标准的C++内存管理机制一样。最后,对于引用计数技术来管理内存是否高效,要具体情况具体分析,不太有可能存在一种机制方法可以解决一切问题。