1.概述
版本:v3.0 beta
語言:c++
<a href="http://www.cocoachina.com/bbs/#">?</a>
1
<code>template</code> <code><</code> <code>class</code> <code>t></code> <code>class</code> <code>cc_dll vector;</code>
cocos2d::vector<t> 是一個封裝了動态大小的數組的順序型容器。
我們很細緻地設計了 cocos2d::vector<t> 容器作為 cocos2d::ccarray 的替代品,是以請使用 cocos2d::vector<t> 代替 cocos2d::ccarray。
cocos2d::vector<t> 常用操作的複雜度(效率)如下:
随機通路 - 常量 0(1)
在末尾插入或者移除元素 - 分攤常量 0(1)
插入或移除元素 - cocos2d::vector<t> 長度線性相關 o(n)
2.模版參數
t - 元素類型.
3.記憶體管理
cocos2d::vector<t> 類包含了唯一一個資料成員:
<code>std::vector<t> _data;</code>
_data 的記憶體管理是由編譯器自動處理的。如果你在棧上聲明了一個 cocos2d::vector<t> 對象,那就不需要關心記憶體釋放問題。
如果你調用了 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 已實作的測試例。
這裡提供一個簡單的示例:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<code>//使用預設大小建立一個 vector<sprite*>,然後往其中加入一個精靈</code>
<code>auto</code> <code>sp0 = sprite::create();</code>
<code>sp0->settag(0);</code>
<code>//這裡我們 demo 使用了 shared_ptr,在你的代碼中,請使用棧對象替代 </code>
<code>std::shared_ptr<vector<sprite*>> vec0 = std::make_shared<vector<sprite*>>(); </code> <code>//default constructor</code>
<code>vec0->pushback(sp0);</code>
<code> </code>
<code>//使用capacity為5來建立一個 vector<object*>,然後往其中加入一個精靈</code>
<code>auto</code> <code>sp1 = sprite::create();</code>
<code>sp1->settag(1);</code>
<code>//用一個容量初始化一個 vector</code>
<code>vector<sprite*> vec1(5);</code>
<code>//在一個确定的位置插入一個确定的對象</code>
<code>vec1.insert(0, sp1);</code>
<code>//我們也可以加入一整個 vector</code>
<code>vec1.pushback(*vec0);</code>
<code>for</code> <code>(</code> <code>auto</code> <code>sp : vec1)</code>
<code>{</code>
<code> </code> <code>log</code> <code>(</code> <code>"sprite tag = %d"</code> <code>, sp->gettag());</code>
<code>}</code>
<code>vector<sprite*> vec2(*vec0);</code>
<code>if</code> <code>(vec0->equals(vec2)) { </code> <code>//如果兩個 vector 相同的話傳回真</code>
<code> </code> <code>log</code> <code>(</code> <code>"pvec0 is equal to pvec2"</code> <code>);</code>
<code>if</code> <code>(!vec1.empty()) { </code> <code>//判斷 vector 是否為空</code>
<code> </code> <code>//擷取 vector 的 capacity 和 size,要注意的是 capacity 并不一定等于 size</code>
<code> </code> <code>if</code> <code>(vec1.capacity() == vec1.size()) {</code>
<code> </code> <code>log</code> <code>(</code> <code>"pvec1->capacity()==pvec1->size()"</code> <code>);</code>
<code> </code> <code>}</code> <code>else</code> <code>{</code>
<code> </code> <code>vec1.shrinktofit(); </code> <code>//收縮 vector 以便記憶體對應上元素的數量</code>
<code> </code> <code>log</code> <code>(</code> <code>"pvec1->capacity()==%zd; pvec1->size()==%zd"</code> <code>,vec1.capacity(),vec1.size());</code>
<code> </code> <code>}</code>
<code> </code> <code>//pvec1->swap(0, 1); //通過索引交換 vector 中的兩個元素</code>
<code> </code> <code>vec1.swap(vec1.front(), vec1.back()); </code> <code>//通過值交換 vector 中的兩個元素 </code>
<code> </code> <code>if</code> <code>(vec2.contains(sp0)) { </code> <code>//傳回一個布爾值,用于訓示該對象是否存在于 vector 中</code>
<code> </code> <code>log</code> <code>(</code> <code>"the index of sp0 in pvec2 is %zd"</code> <code>,vec2.getindex(sp0));</code>
<code> </code> <code>//從 vector 中移除元素</code>
<code> </code> <code>vec1.erase(vec1.find(sp0));</code>
<code> </code> <code>//pvec1->erase(1);</code>
<code> </code> <code>//pvec1->eraseobject(sp0,true);</code>
<code> </code> <code>//pvec1->popback();</code>
<code> </code> <code>vec1.clear(); </code> <code>//移除所有元素</code>
<code> </code> <code>log</code> <code>(</code> <code>"the size of pvec1 is %zd"</code> <code>,vec1.size());</code>
輸出:
<code>cocos2d: sprite tag = 1</code>
<code>cocos2d: sprite tag = 0</code>
<code>cocos2d: pvec0 is equal to pvec2</code>
<code>cocos2d: pvec1->capacity()==2; pvec1->size()==2</code>
<code>cocos2d: the index of sp0 in pvec2 is 0</code>
<code>cocos2d: the size of pvec1 is 0</code>
5.最佳實踐
偏向于使用基于棧建構的 cocos2d::vector<t> 而不使用基于堆建構的 cocos2d::vector<t>。
當将 cocos2d::vector<t> 作為參數進行傳遞的時候,将它聲明為一個常引用,如 const cocos2d::vector<t>&。
當從一個函數中傳回一個 cocos2d::vector<t> 時,簡單地傳回值對象。編譯器将使用移動語義優化這種情況。
不要試圖在 cocos2d::vector<t> 中儲存除 cocos2d::object 子類對象指針以外的其他任意資料類型對象。