- 启动APP:创建运行HelloWorld场景
bool AppDelegate::applicationDidFinishLaunching()
{
...
// create a scene. it's an autorelease object
auto scene = HelloWorld::scene();
// run
director->runWithScene(scene);
return true;
}
- 创建HelloWorld场景对象,并将其加入内存自动回收池。
Scene* HelloWorld::scene()
{
return HelloWorld::create();
}
Scene* Scene::create()
{
Scene *ret = new (std::nothrow) Scene();
if (ret && ret->init())
{
ret->autorelease();
return ret;
}
else
{
...
}
}
- 创建 new (std::nothrow) Scene(); 时调用根类构造函数,默认_referenceCount引用计数为1
Ref::Ref()
: _referenceCount(1) // when the Ref is created, the reference count of it is 1
...
- 初始化 * ret->init()* 场景对象后,调用autorelease()函数* ret->autorelease();*,将其加入内存自动回收池。
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
此时,HelloWorld场景对象已经被加入了内存自动回收池,并且引用计数为1
- 运行HelloWorld场景director->runWithScene(scene);。
void Director::runWithScene(Scene *scene)
{
...
pushScene(scene);
...
}
- 将其压入场景栈 * _scenesStack.pushBack(scene)*。
void Director::pushScene(Scene *scene)
{
...
_scenesStack.pushBack(scene);
...
}
- 压入栈操作:将对象添加到vector,同时引用计数+1
/** Adds a new element at the end of the Vector. */
void pushBack(T object)
{
CCASSERT(object != nullptr, "The object should not be nullptr");
_data.push_back( object );
object->retain();
}
void Ref::retain()
{
CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
++_referenceCount;
}
- 到这步,实际上HelloWorld场景对象的引用计数已经为2了(初始化为1,director->runWithScene(scene);操作+1)。
- 主循环mainLoop每帧都会调用PoolManager::getInstance()->getCurrentPool()->clear();方法,清理析构_managedObjectArray未被引用对象(referenceCount==1),同时将_managedObjectArray清空。
void Director::mainLoop()
{
...
else if (! _invalid)
{
drawScene();
// release the objects
PoolManager::getInstance()->getCurrentPool()->clear();
}
}
void AutoreleasePool::clear()
{
...
std::vector releasings;
releasings.swap(_managedObjectArray);
for (const auto &obj : releasings)
{
obj->release();
}
...
}
void Ref::release()
{
CCASSERT(_referenceCount > 0, "reference count should be greater than 0");
--_referenceCount;
if (_referenceCount == 0)
{
...
delete this;
}
}
至此,在下一帧结束前,HelloWorld的场景对象引用计数变成了1。同时由于_managedObjectArray被清空,所以在下下帧时,执行clear就不会再对HelloWorld场景对象做release()处理。也就是说其引用计数保持为1。
- 外记:
当下一次调用 *replaceScene(Scene scene) 方法时,释放HelloWorld场景对象,即其引用计数变为0。
void Director::replaceScene(Scene *scene)
{
...
_scenesStack.replace(index, scene);
...
}
void replace(ssize_t index, T object)
{
CCASSERT(index >= 0 && index < size(), "Invalid index!");
CCASSERT(object != nullptr, "The object should not be nullptr");
_data[index]->release();
_data[index] = object;
object->retain();
}
替换当前索引的场景对象,并将原持有对象释放。