跟着石头哥哥学cocos2d-x(三)---2dx引擎中的内存管理模型
跟着石头哥哥学cocos2d-x(三)---2dx引擎中的内存管理模型
石头哥哥 发表于4年前
跟着石头哥哥学cocos2d-x(三)---2dx引擎中的内存管理模型
  • 发表于 4年前
  • 阅读 4513
  • 收藏 54
  • 点赞 6
  • 评论 6

新睿云服务器60天免费使用,快来体验!>>>   

摘要: cocos2d-x 对象内存管理模型分解

2dx引擎中的对象内存管理模型,很简单就是一个对象池+引用计数,本着学好2dx的好奇心,先这里开走吧,紧接上面两节,首先我们看一个编码场景代码:

hello word :


#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__



#include "HelloWorldScene.h"

USING_NS_CC;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloWorld *layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback));
    
	pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
                                origin.y + pCloseItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition(CCPointZero);
    this->addChild(pMenu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
    
    // position the label on the center of the screen
    pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - pLabel->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(pLabel, 1);

    // add "HelloWorld" splash screen"
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");

    // position the sprite on the center of the screen
    pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    // add the sprite as a child to this layer
    this->addChild(pSprite, 0);
    
    return true;
}


//close application
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}




代码片段中有一个 CREATE_FUNC(HelloWorld);   HelloWorld *layer = HelloWorld::create();

跟进看到,其实创建这个层的方法就是定义的CREATE_FUNC(xx);继续追踪,可以看到,他创建这个层,同时会调用初始化inti()方法--准备layer基础数据,也就是java上见的多的多态,这不是重点,他调用了,autorelease(),也就是我们对象内存模型中的自动管理方法,这里我先直接总结下,对象在创建的过程中,创建之后,调用autorelease(),就会被添加到对象池中自动维护计数,当计数未0(在每一帧结束后),或者在析构中调用销毁,那么就将会冲对象池中移除;在看一个例子:CCArray *test=CCArray::create();test->retain();

这样才是才会创建成功(额排除其他异常);当我们创建这个对象的时候,create()在返回这个对象的同时会将对象自动autorelease();所以你必须还得引用计数+1;为什么?

因为autorelease()将对象添加到对象池中,会自动release(),引用计算--1;默认引用计数为1,当对象创建的时候,所以知道为什么会创建失败了吧 如果标记对象被引用;当然你自己创建的对象就要这样处理,如果是2dx的捏?那就直接穿件创建autorelease(),内存对象池会自动处理的;

接下来直接看内存模型+引用计数,内存对象缓存是用的CCArray;具体看下面代码片段,该有的注解都有了:

先是2dx中:object,java中所有对象的根接点,这里你可以这样“理解”:

/****************************************************************************
Copyright (c) 2010 cocos2d-x.org

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#ifndef __CCOBJECT_H__
#define __CCOBJECT_H__

#include "CCDataVisitor.h"

#ifdef EMSCRIPTEN
#include <GLES2/gl2.h>
#endif // EMSCRIPTEN

NS_CC_BEGIN

/**
 * @addtogroup base_nodes
 * @{
 */

class CCZone;
class CCObject;
class CCNode;
class CCEvent;

class CC_DLL CCCopying
{
public:
    virtual CCObject* copyWithZone(CCZone* pZone);
};
//对象继承CCobject 都可以引用自动释放池对象(引用计数+释放池管理类)
//根据开发的内容来划分池对象,譬如一个场景创建一个自动释放池,游戏中场景切换时,释放缓冲区最好时间
//引擎基类
class CC_DLL CCObject : public CCCopying
{
public:
    // 对象ID
    unsigned int        m_uID;
    // Lua reference id
    int                 m_nLuaID;
protected:
    // 计数对象
    unsigned int        m_uReference;
    // count of autorelease 计数自动释放对象
    unsigned int        m_uAutoReleaseCount;
public:
    CCObject(void);
    virtual ~CCObject(void);
    
    void release(void);
    void retain(void);
    CCObject* autorelease(void);
    CCObject* copy(void);
	bool isSingleReference(void) const;
	unsigned int retainCount(void) const;
	virtual bool isEqual(const CCObject* pObject);

	virtual void acceptVisitor(CCDataVisitor &visitor);

	virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
    //自动释放池
    friend class CCAutoreleasePool;
};


typedef void (CCObject::*SEL_SCHEDULE)(float);
typedef void (CCObject::*SEL_CallFunc)();
typedef void (CCObject::*SEL_CallFuncN)(CCNode*);
typedef void (CCObject::*SEL_CallFuncND)(CCNode*, void*);
typedef void (CCObject::*SEL_CallFuncO)(CCObject*);
typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
//if button ,do CCEvent *evnet  参数
typedef void (CCObject::*SEL_EventHandler)(CCEvent*);
typedef int (CCObject::*SEL_Compare)(CCObject*);
//各种回调函数接口!!!
#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)
#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)
#define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)
#define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)
#define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)
#define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)
#define event_selector(_SELECTOR) (SEL_EventHandler)(&_SELECTOR)
#define compare_selector(_SELECTOR) (SEL_Compare)(&_SELECTOR)

// end of base_nodes group
/// @}

NS_CC_END

#endif // __CCOBJECT_H__



/****************************************************************************
Copyright (c) 2010 cocos2d-x.org

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/


#include "CCObject.h"
#include "CCAutoreleasePool.h"
#include "ccMacros.h"
#include "script_support/CCScriptSupport.h"

NS_CC_BEGIN

CCObject* CCCopying::copyWithZone(CCZone *pZone)
{
    CC_UNUSED_PARAM(pZone);
    CCAssert(0, "not implement");
    return 0;
}

/************************************************************************/
/* 构造函数                                                                     */
/************************************************************************/
CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1
, m_uAutoReleaseCount(0)
{
    static unsigned int uObjectCount = 0;

    m_uID = ++uObjectCount;
}

CCObject::~CCObject(void)
{
    // if the object is managed, we should remove it
    // from pool manager
    if (m_uAutoReleaseCount > 0)
    {
        CCPoolManager::sharedPoolManager()->removeObject(this);
    }

    // if the object is referenced by Lua engine, remove it
    if (m_nLuaID)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(this);
    }
    else
    {
        CCScriptEngineProtocol* pEngine = CCScriptEngineManager::sharedManager()->getScriptEngine();
        if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript)
        {
            pEngine->removeScriptObjectByCCObject(this);
        }
    }
}

CCObject* CCObject::copy()
{
    return copyWithZone(0);
}

//当引用计数为0时,释放对象 delete
void CCObject::release(void)
{
	CCAssert(m_uReference > 0, "reference count should greater than 0");
	--m_uReference;

	if (m_uReference == 0)
	{
		delete this;
	}
}


/************************************************************************/
/* 引用计数         +1 标记对象被引用                                                           */
/************************************************************************/
void CCObject::retain(void)
{
    CCAssert(m_uReference > 0, "reference count should greater than 0");

    ++m_uReference;
}

//将对象添加到释放池中
CCObject* CCObject::autorelease(void)
{
    CCPoolManager::sharedPoolManager()->addObject(this);
    return this;
}

//判断是否单引用 
bool CCObject::isSingleReference(void) const
{
    return m_uReference == 1;
}

unsigned int CCObject::retainCount(void) const
{
    return m_uReference;
}

bool CCObject::isEqual(const CCObject *pObject)
{
    return this == pObject;
}

void CCObject::acceptVisitor(CCDataVisitor &visitor)
{
    visitor.visitObject(this);
}

NS_CC_END



注意当你autoRelease()的时候,就将对象添加到内存CCAutoreleasePool对象中,同时release(),引用计数--1;如果0,不好意思 就干掉;所以创建有些对象要记得引用计数+1,析构中销毁就对了,剩下的交给2dx内存对象模型处理;具体过程看下面代码片段:

/****************************************************************************
Copyright (c) 2010 cocos2d-x.org

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __AUTORELEASEPOOL_H__
#define __AUTORELEASEPOOL_H__

#include "CCObject.h"
#include "CCArray.h"

NS_CC_BEGIN

/**
 * @addtogroup base_nodes
 * @{
 */

class CC_DLL CCAutoreleasePool : public CCObject
{
    CCArray*    m_pManagedObjectArray;    
public:
    CCAutoreleasePool(void);
    ~CCAutoreleasePool(void);

    void addObject(CCObject *pObject);
    void removeObject(CCObject *pObject);

    void clear();
};
//自动释放池
class CC_DLL CCPoolManager
{
    CCArray*    m_pReleasePoolStack;    
    CCAutoreleasePool*                    m_pCurReleasePool;

    CCAutoreleasePool* getCurReleasePool();
public:
    CCPoolManager();
    ~CCPoolManager();
    void finalize();
    void push();
    void pop();

    void removeObject(CCObject* pObject);
    void addObject(CCObject* pObject);

    static CCPoolManager* sharedPoolManager();
    static void purgePoolManager();

    friend class CCAutoreleasePool;
};

// end of base_nodes group
/// @}

NS_CC_END

#endif //__AUTORELEASEPOOL_H__


/****************************************************************************
Copyright (c) 2010 cocos2d-x.org

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCAutoreleasePool.h"
#include "ccMacros.h"

NS_CC_BEGIN

static CCPoolManager* s_pPoolManager = NULL;

//new 一个 array容器。缓存object对象
CCAutoreleasePool::CCAutoreleasePool(void)
{
    m_pManagedObjectArray = new CCArray();
    m_pManagedObjectArray->init();
}

CCAutoreleasePool::~CCAutoreleasePool(void)
{
    CC_SAFE_DELETE(m_pManagedObjectArray);
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
void CCAutoreleasePool::addObject(CCObject* pObject)
{
    m_pManagedObjectArray->addObject(pObject);

    CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");
    ++(pObject->m_uAutoReleaseCount);
	//释放对象 ,如果new 一个 ,那么要标记对象+1 ,回调函数retain(),否则会创建对象失败
    pObject->release(); // no ref count, in this case autorelease pool added.
}
//就是一个从数组中移除对象,java知道吧  List一样的
void CCAutoreleasePool::removeObject(CCObject* pObject)
{
    for (unsigned int i = 0; i < pObject->m_uAutoReleaseCount; ++i)
    {
        m_pManagedObjectArray->removeObject(pObject, false);
    }
}
//释放池中所有对象,在每一帧后,message loop,将会删除autoRelease的对象
void CCAutoreleasePool::clear()
{
    if(m_pManagedObjectArray->count() > 0)
    {
        //CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
        int nIndex = m_pManagedObjectArray->count() - 1;
#endif

        CCObject* pObj = NULL;
        CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)
        {
            if(!pObj)
                break;

            --(pObj->m_uAutoReleaseCount);
            //(*it)->release();
            //delete (*it);
#ifdef _DEBUG
            nIndex--;
#endif
        }

        m_pManagedObjectArray->removeAllObjects();
    }
}


//--------------------------------------------------------------------
//
// CCPoolManager
//
//--------------------------------------------------------------------

CCPoolManager* CCPoolManager::sharedPoolManager()
{
    if (s_pPoolManager == NULL)
    {
        s_pPoolManager = new CCPoolManager();
    }
    return s_pPoolManager;
}

void CCPoolManager::purgePoolManager()
{
    CC_SAFE_DELETE(s_pPoolManager);
}

CCPoolManager::CCPoolManager()
{
    m_pReleasePoolStack = new CCArray();    
    m_pReleasePoolStack->init();
    m_pCurReleasePool = 0;
}

CCPoolManager::~CCPoolManager()
{
    
     finalize();
 
     // we only release the last autorelease pool here 
    m_pCurReleasePool = 0;
     m_pReleasePoolStack->removeObjectAtIndex(0);
 
     CC_SAFE_DELETE(m_pReleasePoolStack);
}

void CCPoolManager::finalize()
{
    if(m_pReleasePoolStack->count() > 0)
    {
        //CCAutoreleasePool* pReleasePool;
        CCObject* pObj = NULL;
        CCARRAY_FOREACH(m_pReleasePoolStack, pObj)
        {
            if(!pObj)
                break;
            CCAutoreleasePool* pPool = (CCAutoreleasePool*)pObj;
            pPool->clear();
        }
    }
}

void CCPoolManager::push()
{
    CCAutoreleasePool* pPool = new CCAutoreleasePool();       //ref = 1
    m_pCurReleasePool = pPool;

    m_pReleasePoolStack->addObject(pPool);                   //ref = 2

    pPool->release();                                       //ref = 1
}

void CCPoolManager::pop()
{
    if (! m_pCurReleasePool)
    {
        return;
    }

     int nCount = m_pReleasePoolStack->count();

    m_pCurReleasePool->clear();
 
      if(nCount > 1)
      {
        m_pReleasePoolStack->removeObjectAtIndex(nCount-1);

//         if(nCount > 1)
//         {
//             m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);
//             return;
//         }
        m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);
    }

    /*m_pCurReleasePool = NULL;*/
}

void CCPoolManager::removeObject(CCObject* pObject)
{
    CCAssert(m_pCurReleasePool, "current auto release pool should not be null");

    m_pCurReleasePool->removeObject(pObject);
}

void CCPoolManager::addObject(CCObject* pObject)
{
    getCurReleasePool()->addObject(pObject);
}


CCAutoreleasePool* CCPoolManager::getCurReleasePool()
{
    if(!m_pCurReleasePool)
    {
        push();
    }

    CCAssert(m_pCurReleasePool, "current auto release pool should not be null");

    return m_pCurReleasePool;
}

NS_CC_END



下面一段摘自:http://blog.csdn.net/ring0hx/article/details/7946397

手动内存管理似乎比new/delete更麻烦,而且并没有解决一开始我们提到的函数内创建的对象的生命周期超出函数怎么办的问题。new和release需配对使用,那在函数内创建的对象返回前我们需要调用一次release,在这之前如果我们没有把对象加入到什么集合中,对象就被销毁了,和使用new/delete是一样的。自动内存管理就可以解决这个问题。CCObject有一个autorelease方法,如果一个对象在用new关键字创建之后调用了autorelease,我们就不必关心它的释放问题。CCPoolManager会在游戏的每一帧结束后自动释放这些autorelease的对象。CCPoolManager其实依然是通过引用计数来管理对象生命周期的,它里面有一个CCAutoreleasePool,我们调用CCObject的autorelease就是把自己加入到CCAutoreleasePool的对象数组里面。当每一帧结束的时候,CCPoolManager会将对象从数组中移除,如果这时候对象的引用计数为0,对象就自然被释放了。 对于用new关键字创建之后调用了autorelease的对象,不需要再release一次。

cocos2dx中的大部分对象都可以通过静态工厂方法来创建出这种会自动释放的对象,这是cocos2dx的一条规则,我们自己实现的类最好也遵循这样的规则,以免引起其他开发人员误会。如果一个对象是通过类的静态方法创建而不是new出来的,我们就不需要release它。

其实这里的自动并没有我们想得那么好,对于像C#,Java这种托管语言,虚拟机为你完成了所有内存管理工作,程序员完全从内存分配和释放中解脱了出来。cocos2dx的autorelease只不过每帧结束后自动在为我们释放了一次对象, 如果我们希望创建的对象在下一帧仍然可以使用,我们需要显式地retain一下这个对象或者把对象加入到集合中(集合会帮我们retain一次)。既然retain了,我们还是不能忘记在适当的地方release。比较常见的用法是创建一个autorelease对象作为类成员变量,我们在通过静态方法得到实例的指针后除了赋值给类成员,还要retain一次,然后在类的析构函数中release一次。如果没有retain,以后使用该成员的时候就会因为对象被销毁而发生内存访问错误,这是新手很容易遇到的陷阱。

想了解更多 你也可以看这里,个人觉得这里翻译,以及写的都不错:http://my.oschina.net/wangxuanyihaha/blog/131735



综上所述,2dc引擎中创建了对象 记得添加到对象池中,以便在合适的时机2dx引擎帮你回收内存,其实这个也不是大问题 洁身自好就没事的( 上了厕所要搽干净pp) 你觉得呢?ps:本系列文章会持续更新,后期就会直接根据各个模块单独demo上起,最后出个游戏demo,有问题的请留言,互相学习












  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 297
博文 187
码字总数 120455
作品 2
评论 (6)
无量神通
C#,java中的使用方式,在C++中和智能指针比较相似:shared_ptr/shared_array.
当然在cocos2dx创建对象的时候都是用shared_ptr,就能很方便的解决“函数内创建的对象的生命周期超出函数怎么办的问题。”,不过可能会造成shared_ptr对象的多次构造/析构,效率上可能没有这种有个单独的内存管理池的方法效率高
天使之翼-正版
既然能力使用C++ 内存管理就是不是问题,内存自动管理对于高效率的开发来说本来就很扯
石头哥哥

引用来自“祝建宾”的评论

既然能力使用C++ 内存管理就是不是问题,内存自动管理对于高效率的开发来说本来就很扯

你这话有点偏激了 高效开发是一个方面 ,毋庸置疑,但是最重要的是站在产品的角度来考虑,那么 稳定 压倒一切,至于是否使用内存管理就好比你连接数据库到底要不要使用连接池,看应用场景来做出合理的选择吧
金尘科技

引用来自“石头哥哥”的评论

引用来自“祝建宾”的评论

既然能力使用C++ 内存管理就是不是问题,内存自动管理对于高效率的开发来说本来就很扯

你这话有点偏激了 高效开发是一个方面 ,毋庸置疑,但是最重要的是站在产品的角度来考虑,那么 稳定 压倒一切,至于是否使用内存管理就好比你连接数据库到底要不要使用连接池,看应用场景来做出合理的选择吧

应该做到既高效又稳定,那么只有经验丰富的C++程序员能做到
石头哥哥

引用来自“牛哄哄”的评论

引用来自“石头哥哥”的评论

引用来自“祝建宾”的评论

既然能力使用C++ 内存管理就是不是问题,内存自动管理对于高效率的开发来说本来就很扯

你这话有点偏激了 高效开发是一个方面 ,毋庸置疑,但是最重要的是站在产品的角度来考虑,那么 稳定 压倒一切,至于是否使用内存管理就好比你连接数据库到底要不要使用连接池,看应用场景来做出合理的选择吧

应该做到既高效又稳定,那么只有经验丰富的C++程序员能做到

这是我们追求的目标 嗯 有丰富经验当然就更好
Lunar_Lin
cocos2dx的内存管理是模仿oc的败笔. 效率上, shared_ptr已经非常不错了.cocos2dx的内存管理方式不会快. 优秀的C++开发者肯定是使用智能指针而不会去手动管理内存. 在复杂的业务逻辑和多线程环境下, 手动管理内存对软件的设计约束太多.
×
石头哥哥
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: