Cocos2d-x3.0模版容器詳解:cocos2d::Vector
阿新 • • 發佈:2019-02-16
1.概述
版本:v3.0 beta
語言:C++
定義在 “COCOS2DX_ROOT/cocos/base” 路徑下的 "CCVector.h" 的標頭檔案中。
[cpp] view
plain copy
print?
在 Cocos2d-x v3.0 beta 之前,存在另一個順序性容器 cocos2d::CCArray,這將會被棄用。
我們很細緻地設計了 cocos2d::Vector<T> 容器作為 cocos2d::CCArray 的替代品,所以請使用 cocos2d::Vector<T> 代替 cocos2d::CCArray。
cocos2d::Vector<T> 常用操作的複雜度(效率)如下:
隨機訪問 - 常量 0(1)
在末尾插入或者移除元素 - 分攤常量 0(1)
插入或移除元素 - cocos2d::Vector<T> 長度線性相關 O(n)
2.模版引數
T - 元素型別.
-T 必須是一個指向 cocos2d::Object 子類物件的指標。不能是其他資料型別或者原生型別,因為我們已經將 Cocos2d-x 的記憶體管理模型整合到 cocos2d::Vector<T> 中(從 v3.0 beta 開始)。
3.記憶體管理
cocos2d::Vector<T> 類包含了唯一一個數據成員:
[cpp] view
plain copy
print?
如果你呼叫了 new 操作符來分配一塊 cocos2d::Vector<T> 的動態記憶體,那就需要在使用完後呼叫 delete 操作符來釋放記憶體。這同樣適用於 new[] 和 delete[]。
注意:在新 C++ 中,它傾向於本地儲存物件而不是堆儲存物件。所以,請不要呼叫 new 操作符來分配 cocos2d::Vector<T> 的堆物件,而是使用棧物件來代替它。
如果你有足夠的理由在堆上動態分配 cocos2d::Vector<T> 的話,請使用智慧指標替換原始指標,比如 Shared_ptr,unique_ptr。
警告: cocos2d::Vector<T> 不是 cocos2d::Object 的子類,因此不再像其他的 cocos2d 類一樣使用 retain/release 和記憶體計數管理。換句話說,你不能對 cocos2d::Vector<T> 本身呼叫 retain,release等等操作。
4.基本用法
我們用一個統一的介面外加 Cocos2d-x 的記憶體管理規則來封裝了 std::vector<T> 基本上所有常用的操作。
所以 pushBack() 方法現在將會 retain 該函參的所有權,popBack() 方法將會 release 容器最後一個元素的所有權。
當你使用這些操作時,你應該加倍注意底層的記憶體管理,這東西對於許多的 Cocos2d-x 開發新手是常見陷阱。
警告:cocos2d::Vector<T> 沒有過載 operator[],所以你不能使用像 vec 這樣的操作來試圖從 cocos2d::Vector<T> 獲取元素。
cocos2d::Vector<T> 容器提供了許多不同種類的迭代器。我們受益於 C++ 標準庫的標準基礎設施;例如,大量專用的標準通用演算法和 for_each 迴圈。
除了 std::vector<T> 容器操作,我們還添加了很多標準演算法到 cocos2d::Vector<T>,比如 std::find,std::reverse 和 std::swap,這樣簡化了很多有用的、常用的操作。
更多 API 的使用,請參考引擎原始碼和 Cocos2d-x 3.0 beta 已實現的測試例。
這裡提供一個簡單的示例:
[objc] view
plain copy
print?
- template<class T>class CC_DLL Vector;
- std::vector<T> _data;
- //使用預設大小建立一個 Vector<Sprite*>,然後往其中加入一個精靈
- auto sp0 = Sprite::create();
- sp0->setTag(0);
- //這裡我們 demo 使用了 shared_ptr,在你的程式碼中,請使用棧物件替代
- std::shared_ptr<Vector<Sprite*>> vec0 = std::make_shared<Vector<Sprite*>>(); //default constructor
- vec0->pushBack(sp0);
- //使用capacity為5來建立一個 Vector<Object*>,然後往其中加入一個精靈
- auto sp1 = Sprite::create();
- sp1->setTag(1);
- //用一個容量初始化一個 vector
- Vector<Sprite*> vec1(5);
- //在一個確定的位置插入一個確定的物件
- vec1.insert(0, sp1);
- //我們也可以加入一整個 vector
- vec1.pushBack(*vec0);
- for(auto sp : vec1)
- {
- log("sprite tag = %d", sp->getTag());
- }
- Vector<Sprite*> vec2(*vec0);
- if (vec0->equals(vec2)) { //如果兩個 vector 相同的話返回真
- log("pVec0 is equal to pVec2");
- }
- if (!vec1.empty()) { //判斷 vector 是否為空
- //獲取 vector 的 capacity 和 size,要注意的是 capacity 並不一定等於 size
- if (vec1.capacity() == vec1.size()) {
- log("pVec1->capacity()==pVec1->size()");
- }else{
- vec1.shrinkToFit(); //收縮 vector 以便記憶體對應上元素的數量
- log("pVec1->capacity()==%zd; pVec1->size()==%zd",vec1.capacity(),vec1.size());
- }
- //pVec1->swap(0, 1); //通過索引交換 vector 中的兩個元素
- vec1.swap(vec1.front(), vec1.back()); //通過值交換 vector 中的兩個元素
- if (vec2.contains(sp0)) { //返回一個布林值,用於指示該物件是否存在於 vector 中
- log("The index of sp0 in pVec2 is %zd",vec2.getIndex(sp0));
- }
- //從 vector 中移除元素
- vec1.erase(vec1.find(sp0));
- //pVec1->erase(1);
- //pVec1->eraseObject(sp0,true);
- //pVec1->popBack();
- vec1.clear(); //移除所有元素
- log("The size of pVec1 is %zd",vec1.size());
- }
- Cocos2d: sprite tag = 1
- Cocos2d: sprite tag = 0
- Cocos2d: pVec0 is equal to pVec2
- Cocos2d: pVec1->capacity()==2; pVec1->size()==2
- Cocos2d: The index of sp0 in pVec2 is 0
- Cocos2d: The size of pVec1 is 0