cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

cocos2d-x利用引用计数进行内存自动管理,

是什么原理?

为什么能自动释放对象?

怎么做到的每帧最后释放?

 

研究cocos2d-x源码

所有继承自Ref的类,都可以做到自动释放实例,来看整个过程,

1、先看Ref类构造方法,所有Ref子类,创建后引用计数为初始为 1

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

2、Node * node = Node::create();   

    此时node的引用计数为1,create()方法中执行了 autorelease()方法,把实例node加入当前的内存管理池中,如下

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

3、把node加入场景树, parent->addChild(node);

     addChild方法中,把node的引用计数再+1,  此时node的引用计数为 2

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

 

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

 

4、在mainLoop中每帧最后执行

     PoolManager::getInstance()->getCurrentPool()->clear();

     clear()方法,遍历内存管理池中所有对象,调用release(), 引用计数都减1,此时 node的引用计数为 1,

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

    注意,这里std::vector类的swap方法用得巧妙,

    首先把 _managedObjectArray 中对象列表的指针换给了releasings,_managedObjectArray变成了一个空列表,

    然后,因为releasings是局部变量,在生命周期结束后,就会析构,把对象列表都释放掉;

 

5、此时node的引用计数为1,且在场景树中,parent 的成员_children持有node,

     当node被移除时,会执行 release()方法,引用计数再减1,变成0,此时释放对象;

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

 

 

 

  

 

C++ vector容器的swap方法

刚才在研究cocos2d-x源码,

PoolManager::getInstance()->getCurrentPool()->clear();

clear()方法的这么几行代码:

void AutoreleasePool::clear()
{
std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);
for (const auto &obj : releasings)
{
obj->release();
}
}

AutoreleasePool是一个用来托管内存的对象池,_managedObjectArray是一个std::vector<Ref*>类型的成员,用来保存所有管理的对象,

这几行代码要做的事情就是:遍历所有对象,依次调用他们的release()方法,最后清空这个vector。
但是注意到这两句:

std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);

把一个默认的临时对象和原有的成员进行了swap,然后对交换后的临时对象进行遍历。

这看起来好像是有点多余?为什么不直接遍历_managedObjectArray,然后再调用其clear()方法呢?

《Effective STL》第17条:从vector中删除元素缩减了该vector的大小(size),但是并没有减小它的容量(capacity)。

了解STL的同学都知道size和capacity的区别,

那么这里的swap调用就能清楚作者意图了:遍历完vector后还要释放其所占的内存,简单地调用clear方法并不能解决问题。

swap方法的原理是交换两个vector的内部指针以达到“交换整个容器”的效果,

所以在和默认的临时变量swap后,成员变量_managedObjectArray确实是个空的容器(包括内存),

临时变量在函数结束时析构,而vector正是在其析构函数中释放内存的,所以在函数结束时,所有多余的内存都被释放。

 

这样的技巧可以用来清空一个vector的内存:

vector<T>().swap(_vectorToBeReleased);

其效果等价于(注意花括号):
{
vector<T> temp;
temp.swap(_vectorToBeReleased);
}

该技巧同样适用于std::string。

原文链接: https://www.cnblogs.com/xingchong/p/13051621.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    cocos2dx——引用计数与内存自动管理 C++ vector容器的swap方法

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/353027

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午7:50
下一篇 2023年3月2日 上午7:50

相关推荐