首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Cocos2d-x C++ 內存管理:create() 與 new + autorelease 的釋放邏輯

     編輯:程式設計綜合問答

代碼片段

auto layer = new AccelerometerTest();
addChild(layer);
layer->release(); // 為什麼要 release?

核心機制:引用計數

Cocos2d-x 物件繼承 Ref,採用**手動引用計數** (類似 COM/Objective-C MRC)。

  • new:分配記憶體,**引用計數 = 1** (你擁有它)。
  • addChild(node):父節點會呼叫 node->retain(),**引用計數 +1 = 2** (父節點也擁有它)。
  • release():引用計數 -1。歸 0 時自動 delete this。

為什麼要 layer->release()?

平衡 new 帶來的初始擁有權。

  1. 你 new 了 → 你負責釋放 (計數 1)。
  2. addChild 讓父節點也擁有它 (計數 2)。
  3. 你調用 release() → 計數變 1 (僅父節點擁有)。
  4. 場景切換/移除時,父節點 removeChild → release() → 計數歸 0 → 記憶體釋放。**完美無洩漏。**

若不寫 release() 會怎樣?

  • 計數卡在 2。
  • 父節點移除時 release() → 計數變 1 ≠ 0。
  • 物件**永不釋放** → **記憶體洩漏**。

現代寫法:靜態工廠方法 create() (自動 autorelease)

// 標準 Cocos2d-x 節點類都有這個靜態方法
auto layer = AccelerometerTest::create(); // 內部:new -> init() -> autorelease() -> return
// autorelease() 將物件放入「自動釋放池」,當前幀結束時自動 release() 一次。

addChild(layer); // retain() -> 計數 1 (父節點擁有)
// **此處絕對不能再手動 release()!** 因為你沒有初始擁有權 (已被 autorelease 標記)。

// 父節點移除時 release() -> 計數 0 -> 釋放。正確。

對比總結

寫法創建addChild 後計數需手動 release?適用場景
new Class()計數 1 (你擁有)2是 (平衡 new)需立即控制生命週期、非節點類、舊代碼維護
Class::create()計數 1 + autorelease 標記1 (父節點擁有)否 (會過度釋放崩潰)**現代標準推薦**,所有繼承 Ref 的節點類

進階:autorelease() 原理

// 簡化版實現
Ref* Ref::autorelease() {
    PoolManager::getInstance()->getCurrentPool()->addObject(this);
    return this;
}
// 每幀結束 Director::mainLoop -> PoolManager::getCurrentPool()->clear() 
// -> 遍歷池內物件呼叫 release()。

**注意**:autorelease 不是「立即釋放」,而是「延遲到幀結束釋放」。這保證了 create() 返回的物件在當前函數棧幀內安全可用,且若隨即 addChild 被 retain,則自動釋放池的 release 只是抵消 create 內部的隱性擁有權,不影響父節點的擁有權。

總結

代碼中 new ...; addChild; release(); 是**正確的手動管理模式** (平衡 new 的擁有權)。
**現代開發請直接用 Class::create() 並省略 release()**,讓自動放池和父子關係自動管理生命週期,更安全、更簡潔、更符合框架設計意圖。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved