【已解决】一个内存机制问题

假如只有一个精灵pSprite 创建+1 添加进场景+1,他的引用计数是2,那程序每帧循环的时候 引用计数-1,那岂不是在第二帧结束的时候 这个精灵不就是野指针了吗?

谁说每帧-1的,就创建的该帧结束后-1

嗯,如果没记错,有继承 cocos2d::CCRef (2.x 版)、cocos2d::Ref (3.0 版) ,于建立物件后(以 create() 呼叫)会把该物件加入物件池 PoolManager 中。

物件池在该帧结束后会将物件池中的所有物件的引用计数 -1,所以,如果这时该物件没有被隶属于任何其他容器物件底下的话,引用计数就会降成 0,然后就被释放。

刚开始看 cocos2d-x 时,上网看了半天其他人的内存机制教学,讲的都很不具体,后来干脆直接看代码,马上就清楚明白了。

底下大概讲一下我所理解的流程,希望能帮上点忙。

By the way,由于是台湾同胞,用词恐怕会有些不太一样(尽量有用内地的词汇了),请多包涵。

  1. 呼叫 cocos2d::Sprite::create( ) 建立物件,此时 Sprite 的引用计数为 1 (cocos2d::Ref 派生类的基础值)

  2. 由于建立时事透过 cocos2d::Sprite::create( ) 函数,而该函数会呼叫 autorelese( ),这个会将被建立出来的物件加入 PoolManager 物件池中。

  3. 在该帧结束时,PoolManager 物件池会将所以物件池中所有保有的物件引用计数 -1(呼叫 release() 来达成)。

  4. PoolManager 物件池遍循过所有的保有物件一次后,会将保有的物件指针全清除干净,所以不会有每一帧都 -1 的情况出现。

  5. 如果刚刚被建立的 Sprite 物件没有被加入其他容器物件底下的话,引用指针此时就会降到 0,于是乎就会被释放掉噜。

那么,如果刚才建立的 Sprite 有被加到其他容器物件中的话呢?

  1. 一般在透过 addChild( ) 把刚建立加入其他容器物件时,会呼叫该物件的 retain( ) 一次,这时引用指针会 +1,于是在呼叫 addChild( ) 后引用计数会是 2!

  2. 与步骤 3 一样,该帧结束后物件池把该物件的引用计数 -1,所以,之后这个 Sprite 的引用计数就会一直维持在 1。

就这么简单(?),没有什么其他玄玄妙妙的地方。

以上。

你理解错了,在第二帧的时候它就不在内存池中了,每帧结束都会释放一次内存池的,然后下一帧的时候新建一个内存池,以后的autorelease对象会添加到这个内存池中,而你第一帧中的那些对象是不存在的。可以看看这个http://www.cocoachina.com/bbs/read.php?tid=195219&fpage=3

“然后下一帧的时候新建一个内存池,以后的autorelease对象会添加到这个内存池中,”怎么理解这句话,程序不是每一帧就运行了所有的项目,所有的autorelease的对象在第一帧的时候就全部添加进内存池了吗?

恩,谢啦。、

看来是我理解错了 - -

感谢台湾同胞相当通熟易懂的解说Cocos2d-x内存引用计数管理。虽然用词有点不一样,但是原理解析深入浅出了。:801::801::801:

不是那个意思哈,程序不是一帧就把所有的autorelease对象放进内存池的,你不可能一次创建好了所有的对象吧。

还不理解可以看看这个http://www.cocoachina.com/bbs/read.php?tid=195219&fpage=2

我看过源码和你的那篇文章,还是有一些困惑,CCDirector::sharedDirector()->mainLoop();就是控制每一帧的循环吧?CCPoolManager::sharedPoolManager()->pop()那所有的对象的应该是在每一次循环内执行release操作,并且释放上一帧的内存池。所以你说的“程序不是一帧就把所有的autorelease对象放进内存池的,你不可能一次创建好了所有的对象吧。 ”我不是特别明白为什么不能一次创建好所有的对象,那cocos2d-x是如何创建的?能指导下这些吗?

:2::14::13::12::11::10: