(二)内存管理

来源:互联网 发布:js 替换特殊字符 编辑:程序博客网 时间:2024/06/05 10:43

cocos2d版本:3.15

VS版本:2015

找CCObject.h文件,搜索了一下文件目录,还是没找到
后来发现新版的源代码似乎有点不太一样,
我看到director类是继承了Ref这个类的:

class CC_DLL Director : public Ref
使用的是Ref这个类来进行引用计数(在新版本中应该是以此来替代CCObject类了)

class CC_DLL Ref{public:    /**     * Retains the ownership.     *     * This increases the Ref's reference count.     *     * @see release, autorelease     * @js NA     */    void retain();    /**     * Releases the ownership immediately.     *     * This decrements the Ref's reference count.     *     * If the reference count reaches 0 after the decrement, this Ref is     * destructed.     *     * @see retain, autorelease     * @js NA     */    void release();    /**     * Releases the ownership sometime soon automatically.     *     * This decrements the Ref's reference count at the end of current     * autorelease pool block.     *     * If the reference count reaches 0 after the decrement, this Ref is     * destructed.     *     * @returns The Ref itself.     *     * @see AutoreleasePool, retain, release     * @js NA     * @lua NA     */    Ref* autorelease();    /**     * Returns the Ref's current reference count.     *     * @returns The Ref's reference count.     * @js NA     */    unsigned int getReferenceCount() const;protected:    /**     * Constructor     *     * The Ref's reference count is 1 after construction.     * @js NA     */    Ref();public:    /**     * Destructor     *     * @js NA     * @lua NA     */    virtual ~Ref();protected:    /// count of references    unsigned int _referenceCount;    friend class AutoreleasePool;#if CC_ENABLE_SCRIPT_BINDINGpublic:    /// object id, ScriptSupport need public _ID    unsigned int        _ID;    /// Lua reference id    int                 _luaID;    /// scriptObject, support for swift    void* _scriptObject;    /**     When true, it means that the object was already rooted.     */    bool _rooted;#endif    // Memory leak diagnostic data (only included when CC_REF_LEAK_DETECTION is defined and its value isn't zero)#if CC_REF_LEAK_DETECTIONpublic:    static void printLeaks();#endif};
当回收池自身被释放的时候,它就会对池中的所有对象执行一次 release()方法,实现灵活的垃圾回收。
引擎在每次游戏循环开始之前也会创建一个回收池,在循环结束后释放回收池。因此,即使我们没有手工创建和释放回收池,每一帧结束的时候,自动回收池中的对象也都会被执行一次 release()方法。

这边想按照《cocos2d高级开发教程》中的示例代码进行学习,如下:

fish = new CCSprite();fish->init();CCLog("retainCount after init: %d", fish->retainCount());fish->retain();CCLog("retainCount after retain: %d", fish->retainCount());fish->release();CCLog("retainCount after release: %d", fish->retainCount());fish->autorelease();CCLog("retainCount after autorelease: %d", fish->retainCount());
报警告:
警告 C4996 'cocos2d::CCSprite': 被声明为已否决 cc_project_1e:\cocos_project\cc_project_1\classes\helloworldscene.cpp31

后来发现,是版本不同,命名不一致的问题,应该改为:

auto fish = new Sprite();fish->init();cocos2d::log("retainCount after init: %d", fish->getReferenceCount());fish->retain();cocos2d::log("retainCount after retain: %d", fish->getReferenceCount());fish->release();cocos2d::log("retainCount after release: %d", fish->getReferenceCount());fish->autorelease();cocos2d::log("retainCount after autorelease: %d", fish->getReferenceCount());
点击调试后:



注意到是用“开始调试”才能看到输出的log信息,“开始执行”则看不到!!!如图:

在学习自己生成内存池的过程遇到了问题:
书上的代码也是不能适应新版本的,如下:

CCPoolManager::sharedPoolManager()->push();for(int i=0; i<n; i++){CCString* dataItem = CCString::createWithFormat("%d", Data[i]);stringArray->addObject(dataItem);}CCPoolManager::sharedPoolManager()->pop();
后来通过查看base文件下的  CCAutoreleasePool.h  和  CCAutoreleasePool.cpp 这2个文件,发现一下事实:

1.push函数是需要传入参数的

2.push和pop函数已经声明为私有成员函数了,没法像上面这样直接调用

3.PoolManager类里面有了一个友元类 AutoreleasePool

4.在AutoreleasePool类的初始化函数中,进行了push入内存池栈的操作,析构函数中进行了pop操作,也就是说我们不用手动push和pop(私有成员函数,我们也没法手动执行push和pop),其核心代码如下:

AutoreleasePool::AutoreleasePool(const std::string &name): _name(name)#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0), _isClearing(false)#endif{    _managedObjectArray.reserve(150);    PoolManager::getInstance()->push(this);}AutoreleasePool::~AutoreleasePool(){    CCLOGINFO("deallocing AutoreleasePool: %p", this);    clear();        PoolManager::getInstance()->pop();}


从《cocos2d高级开发教程》中更改后的实例代码如下:

AutoreleasePool* stringArray = new AutoreleasePool("test");//自动push入内存池栈中int n = 5;int Data[5] = { 0,1,2,3,4 };for (int i = 0; i<n; i++){String* dataItem = String::createWithFormat("%d", Data[i]);stringArray->addObject(dataItem);}delete stringArray;

关于内存池管理栈,可以查看《cocos2d高级开发教程》中的内存管理章节的最后部分,深入浅出,讲的很容易理解,有图有真相!