• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            cocos2dx 內(nèi)存管理

            轉(zhuǎn)載自:http://blog.csdn.net/ring0hx/article/details/7946397

            cocos2dx的內(nèi)存管理移植自O(shè)bjective-C, 對(duì)于沒(méi)有接觸過(guò)OC的C++開(kāi)發(fā)人員來(lái)說(shuō)是挺迷惑的。不深入理解內(nèi)存管理是無(wú)法寫(xiě)出好的C++程序的,我用OC和cocos2dx也有一段時(shí)間了,在此總結(jié)一下,希望對(duì)想用cocos2dx開(kāi)發(fā)游戲的朋友有所幫助。

            C++的動(dòng)態(tài)內(nèi)存管理一般建議遵循誰(shuí)申請(qǐng)誰(shuí)釋放的原則,即誰(shuí)通過(guò)new操作符創(chuàng)建了對(duì)象,誰(shuí)就負(fù)責(zé)通過(guò)delete來(lái)釋放對(duì)象。如果對(duì)象的生命周期在一個(gè)函數(shù)內(nèi),這很容易做到,在函數(shù)返回前delete就行了。但一般我們?cè)诤瘮?shù)中new出來(lái)的對(duì)象的生命周期都會(huì)超出該函數(shù)體(例如作為函數(shù)的返回值),否則我們可以直接在棧上創(chuàng)建對(duì)象,不需要使用動(dòng)態(tài)內(nèi)存,也省去了內(nèi)存管理的麻煩(當(dāng)然大對(duì)象是不適合在棧上分配的)。如果對(duì)象的生命周期超出了創(chuàng)建對(duì)象的函數(shù),我們就很難再遵循誰(shuí)申請(qǐng)誰(shuí)釋放的原則了,我們必須在函數(shù)外的某個(gè)合適的地方釋放對(duì)象,如果這個(gè)對(duì)象同時(shí)被多個(gè)對(duì)象引用,問(wèn)題就很復(fù)雜了,必須保證所有該對(duì)象的引用者都不再需要它了才可以釋放,在實(shí)際使用中這點(diǎn)是很難保證的。于是,各種內(nèi)存管理技術(shù)應(yīng)運(yùn)而生了:垃圾回收器,智能指針,引用計(jì)數(shù)...... cocos2dx移植于Objective-C,因此和OC一樣使用了比較原始的引用計(jì)數(shù)的方法來(lái)管理內(nèi)存。

            cocos2dx通過(guò)CCObject和CCPoolManager來(lái)實(shí)現(xiàn)內(nèi)存管理。所有使用cocos2dx引用計(jì)數(shù)機(jī)制的類(lèi)都必須派生自CCObject。CCObject有一個(gè)計(jì)數(shù)器成員變量m_uReference,當(dāng)CCObject被構(gòu)造時(shí)m_uReference=1,表示該對(duì)象被引用1次。CCObject的retain方法可以使計(jì)數(shù)器加1,release方法可以使計(jì)數(shù)器減1。當(dāng)計(jì)數(shù)器減到0時(shí)release方法會(huì)通過(guò)delete this來(lái)銷(xiāo)毀自己。

            手動(dòng)內(nèi)存管理
            使用retain和release,我們可以手動(dòng)管理內(nèi)存, 通過(guò)new 創(chuàng)建的對(duì)象,使用release來(lái)釋放。
            CCObject *obj=new CCObject();
             
            obj
            ->release();
            和new\delete需配對(duì)使用一樣,new\release也要配對(duì)使用才可確保內(nèi)存被釋放。有人會(huì)說(shuō)這個(gè)把delete換成release有意義嗎?需要注意的是這個(gè)的release并不等同于delete,release只是表示引用計(jì)數(shù)減1,并不是真正銷(xiāo)毀obj所占用的內(nèi)存。只有當(dāng)obj的引用計(jì)數(shù)為0時(shí)內(nèi)存才會(huì)被銷(xiāo)毀。下面的代碼就展示了release和delete不同:
            CCArray *array = CCArray::array();
            CCObject 
            *obj = new CCObject();// m_uReference=1
            array->addObject(obj); // CCArray的addObject方法會(huì)自動(dòng)調(diào)用obj的retain方法,使引用計(jì)數(shù)加1,表示擁有obj,此時(shí)m_uReference=2
            obj->release(); // 這里的release和new配對(duì),obj引用計(jì)數(shù)減1,但是并不會(huì)釋放obj, 此時(shí)m_uReference=1;
            obj->doSomething(); // 在release之后我們依然可以正常使用obj,它并沒(méi)有被釋放
            array->removeObject(obj); //當(dāng)我們把obj從CCArray中移除時(shí),CCArray會(huì)自動(dòng)調(diào)用obj的release,此時(shí)m_uReference=0, obj被銷(xiāo)毀
            obj->doSomething(); // 錯(cuò)誤,obj已經(jīng)被銷(xiāo)毀
            對(duì)于手動(dòng)內(nèi)存管理,我們需遵循new/release,retain/release配對(duì)使用的原則,誰(shuí)new,誰(shuí)release;誰(shuí)retain,誰(shuí)release。
            new出來(lái)的對(duì)象如果是要加入到cocos2dx集合中,添加完后一定不要忘記release,集合類(lèi)已經(jīng)為你retain了對(duì)象,你還是要為你的new配對(duì)release一次,否則當(dāng)這個(gè)對(duì)象從集合中移除時(shí)不會(huì)被正確銷(xiāo)毀。

            自動(dòng)內(nèi)存管理
            手動(dòng)內(nèi)存管理似乎比new/delete更麻煩,而且并沒(méi)有解決一開(kāi)始我們提到的函數(shù)內(nèi)創(chuàng)建的對(duì)象的生命周期超出函數(shù)怎么辦的問(wèn)題。new和release需配對(duì)使用,那在函數(shù)內(nèi)創(chuàng)建的對(duì)象返回前我們需要調(diào)用一次release,在這之前如果我們沒(méi)有把對(duì)象加入到什么集合中,對(duì)象就被銷(xiāo)毀了,和使用new/delete是一樣的。自動(dòng)內(nèi)存管理就可以解決這個(gè)問(wèn)題。CCObject有一個(gè)autorelease方法,如果一個(gè)對(duì)象在用new關(guān)鍵字創(chuàng)建之后調(diào)用了autorelease,我們就不必關(guān)心它的釋放問(wèn)題。CCPoolManager會(huì)在游戲的每一幀結(jié)束后自動(dòng)釋放這些autorelease的對(duì)象。CCPoolManager其實(shí)依然是通過(guò)引用計(jì)數(shù)來(lái)管理對(duì)象生命周期的,它里面有一個(gè)CCAutoreleasePool,我們調(diào)用CCObject的autorelease就是把自己加入到CCAutoreleasePool的對(duì)象數(shù)組里面。當(dāng)每一幀結(jié)束的時(shí)候,CCPoolManager會(huì)將對(duì)象從數(shù)組中移除,如果這時(shí)候?qū)ο蟮囊糜?jì)數(shù)為0,對(duì)象就自然被釋放了。對(duì)于用new關(guān)鍵字創(chuàng)建之后調(diào)用了autorelease的對(duì)象,不需要再release一次。

            cocos2dx中的大部分對(duì)象都可以通過(guò)靜態(tài)工廠方法來(lái)創(chuàng)建出這種會(huì)自動(dòng)釋放的對(duì)象,這是cocos2dx的一條規(guī)則,我們自己實(shí)現(xiàn)的類(lèi)最好也遵循這樣的規(guī)則,以免引起其他開(kāi)發(fā)人員誤會(huì)。如果一個(gè)對(duì)象是通過(guò)類(lèi)的靜態(tài)方法創(chuàng)建而不是new出來(lái)的,我們就不需要release它。

            其實(shí)這里的自動(dòng)并沒(méi)有我們想得那么好,對(duì)于像C#,Java這種托管語(yǔ)言,虛擬機(jī)為你完成了所有內(nèi)存管理工作,程序員完全從內(nèi)存分配和釋放中解脫了出來(lái)。cocos2dx的autorelease只不過(guò)每幀結(jié)束后自動(dòng)在為我們釋放了一次對(duì)象,如果我們希望創(chuàng)建的對(duì)象在下一幀仍然可以使用,我們需要顯式地retain一下這個(gè)對(duì)象或者把對(duì)象加入到集合中(集合會(huì)幫我們r(jià)etain一次)。既然retain了,我們還是不能忘記在適當(dāng)?shù)牡胤絩elease。比較常見(jiàn)的用法是創(chuàng)建一個(gè)autorelease對(duì)象作為類(lèi)成員變量,我們?cè)谕ㄟ^(guò)靜態(tài)方法得到實(shí)例的指針后除了賦值給類(lèi)成員,還要retain一次,然后在類(lèi)的析構(gòu)函數(shù)中release一次。如果沒(méi)有retain,以后使用該成員的時(shí)候就會(huì)因?yàn)閷?duì)象被銷(xiāo)毀而發(fā)生內(nèi)存訪問(wèn)錯(cuò)誤,這是新手很容易遇到的陷阱。

            posted on 2012-12-15 15:18 楊粼波 閱讀(1657) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 文章收藏 、C++

            久久精品无码专区免费东京热| 国产精品久久99| 无码人妻久久一区二区三区免费| 久久国产免费直播| 欧美丰满熟妇BBB久久久| 久久91综合国产91久久精品| 久久婷婷色综合一区二区| 模特私拍国产精品久久| 国产精品久久久久9999| 国产精品久久新婚兰兰| 久久99精品国产| 少妇熟女久久综合网色欲| 18岁日韩内射颜射午夜久久成人| 97香蕉久久夜色精品国产 | 久久精品国产国产精品四凭| 久久人人爽人人爽人人片AV麻烦 | 久久天堂AV综合合色蜜桃网| 国产三级精品久久| 国产精品久久久久无码av| 婷婷综合久久中文字幕蜜桃三电影| 久久亚洲欧美日本精品| 久久国产免费观看精品3| 青青久久精品国产免费看| 久久精品国产免费一区| 久久国产精品无码一区二区三区| 思思久久精品在热线热| 久久久久99这里有精品10 | 色婷婷噜噜久久国产精品12p| 国产精品久久久久久搜索| 久久久久久亚洲AV无码专区 | 99久久婷婷国产综合亚洲| 狠狠综合久久AV一区二区三区| 久久伊人精品青青草原日本| 国産精品久久久久久久| 91精品国产91久久久久久蜜臀 | 99久久99久久精品国产片果冻 | 欧美噜噜久久久XXX| 久久久国产乱子伦精品作者| 久久久国产精华液| 久久亚洲精精品中文字幕| 久久久久久无码Av成人影院|