再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的属性和方法后,CCObject还剩下什么?
1.剩下什么?
可以看到整个CCObject就是围绕着m_uReference和m_uAutoReleaseCount在转。这两个变量的解释如下。所以CCObject剩下的其实就是对内存的管理。
- CCObject::CCObject(void)//构造函数
- : m_nLuaID(0)
- , m_uReference(1) //引用计数,初始为1,当引用计数=0,自动释放该对象
- , m_uAutoReleaseCount(0)//自动释放对象计数,如果是手动new的,则为0,如果autoRelease的,则在AutoreleasePool会+1
- //这里是保护成员,所以CCAutoreleasePool被声明为友元类
- {
- static unsigned int uObjectCount = 0;//静态成员,对象的计数,只增不减,用于标识唯一一个对象实例
- m_uID = ++uObjectCount;
- }
- CCObject::~CCObject(void)
- {
- if (m_uAutoReleaseCount > 0)//如果是自动管理,则在PoolManager中删除
- {
- 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);
- }
- }
- }
- void CCObject::release(void)//引用计数-1,如果引用计数=0,释放对象
- {
- CCAssert(m_uReference > 0, "reference count should greater than 0");
- --m_uReference;
- if (m_uReference == 0)
- {
- delete this;
- }
- }
- void CCObject::retain(void)//引用计数+1,防止被对象释放
- {
- CCAssert(m_uReference > 0, "reference count should greater than 0");
- ++m_uReference;
- }
- CCObject* CCObject::autorelease(void)//对象加入PoolManager,自动管理
- {
- 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);
- }
2.内存管理
从CCObject可以看出,内存的管理方式有两种:手动管理和自动管理。
2.1.手动内存管理
想必从Java转到C++的朋友可能很受不了C++再申请完内存后还要手动释放,就像我从C++转Java时也同样很不习惯竟然不用管理内存,老是害怕会不小心让系统给销毁了。CCObject的成员变量m_uAutoReleaseCount标识了是手动管理还是自动管理。如果执行以下操作:
- CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1
- obj->release();//m_uReference-1后为0,执行delete this;
2.2.自动内存管理
如果需要进行内存的自动管理,那要怎么做呢?
- CCObject* obj=new CCObject();//m_uAutoReleaseCount=0,m_uReference=1
- obj->autorelease();//m_uAutoReleaseCount=1,m_uReference=1
好了,什么都不用做,obj自生自灭了。
如果我们需要随时用到obj,而不愿意让它在我们不知情的情况下被释放,那么使用:
- obj->retain();//m_uAutoReleaseCount=1,m_uReference=2
- obj->release();//m_uAutoReleaseCount=1,m_uReference=1
又恢复回去了,所以,retain和release是好基友,一般在自动内存管理使用。
2.3.一个疑问
平时我们可能会这么用:
- //CTestLayer.h
- class CTestLayer : public cocos2d::CCLayer
- {
- public:
- virtual bool init();
- CREATE_FUNC(CTestLayer);
- virtual void update(float delta);
- private:
- CCSprite* background;
- };
- //CTestLayer.cpp
- bool CTestLayer::init()
- {
- if ( !CCLayer::init() )
- {
- return false;
- }
- background=CCSprite::create("background.png");
- this->addChild(background);
- this->scheduleUpdate();
- return true;
- }
- void update(float delta)
- {
- background->setPositionY(background->getPositionY()-0.1);
- }
- this->addChild(background);
至于为什么,大家翻一下addChild实现源码就知道啦~