cocos2d::Vector

內存管理

cocos2d::Vector<T>類只包含一個成員數據:

std::vector<T> _data;

_data的內存管理是由編譯器自動處理的,如果聲明瞭一個cocos2d::Vector<T>類型,就不必費心去釋放內存。
注意:使用現代的c++,本地存儲對象比堆存儲對象好。所以請不要用new操作來申請cocos2d::Vector<T>的堆對象,請使用棧對象。
如果真心想動態分配堆cocos2d::Vector<T>,請將原始指針用智能指針來覆蓋。
警告cocos2d::Vector<T>並不是cocos2d::Object的子類,所以不要像使用其他cocos2d類一樣來用retain/release和引用計數內存管理。

基本用法

作者們用std::vector<T>的基本操作加上cocos2d-x的內存管理規則來覆蓋該模版原先的普通操作。
所以pushBack()操作將會保留傳遞過來的參數,而popBack()則會釋放掉容器中最後的一個元素。
當你使用這些操作的時候,你需要特別注意這些受託管的對象,對於新手來說,這往往是陷阱。
警告:cocos2d::Vector<T>並沒有重載[]操作,所以不能直接用下標[i]來獲取第i位元素。
cocos2d::Vector<T>提供了不同類型的迭代器,所以我們可以受益於c++的標準函數庫,我們可以使用大量標準泛型算法和for_each循環。
除了std::vector容器的操作之外,開發者們還加入許多標準算法諸如:std::findstd::reversestd::swap,這些算法可以簡化很多通用的操作。
要了解更多的api用例,可以參考cocos2d-x 3.0beta的源碼和壓縮包裏附帶的例子。
下面是一些簡單的例子:

//create Vector<Sprite*> with default size and add a sprite into it
auto sp0 = Sprite::create();
sp0->setTag(0);
//here we use shared_ptr just as a demo. in your code, please use stack object instead
std::shared_ptr<Vector<Sprite*>>  vec0 = std::make_shared<Vector<Sprite*>>();  //default constructor
vec0->pushBack(sp0);

//create a Vector<Object*> with a capacity of 5 and add a sprite into it
auto sp1 = Sprite::create();
sp1->setTag(1);

//initialize a vector with a capacity
Vector<Sprite*>  vec1(5);
//insert a certain object at a certain index
vec1.insert(0, sp1);

//we can also add a whole vector
vec1.pushBack(*vec0);

for(auto sp : vec1)
{
    log("sprite tag = %d", sp->getTag());
}

Vector<Sprite*> vec2(*vec0);
if (vec0->equals(vec2)) { //returns true if the two vectors are equal
    log("pVec0 is equal to pVec2");
}
if (!vec1.empty()) {  //whether the Vector is empty
    //get the capacity and size of the Vector, noted that the capacity is not necessarily equal to the vector size.
    if (vec1.capacity() == vec1.size()) {
        log("pVec1->capacity()==pVec1->size()");
    }else{
        vec1.shrinkToFit();   //shrinks the vector so the memory footprint corresponds with the number of items
        log("pVec1->capacity()==%zd; pVec1->size()==%zd",vec1.capacity(),vec1.size());
    }
    //pVec1->swap(0, 1);  //swap two elements in Vector by their index
    vec1.swap(vec1.front(), vec1.back());  //swap two elements in Vector by their value
    if (vec2.contains(sp0)) {  //returns a Boolean value that indicates whether object is present in vector
        log("The index of sp0 in pVec2 is %zd",vec2.getIndex(sp0));
    }
    //remove the element from the Vector
    vec1.erase(vec1.find(sp0));
    //pVec1->erase(1);
    //pVec1->eraseObject(sp0,true);
    //pVec1->popBack();

    vec1.clear(); //remove all elements
    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

最佳做法

  • 考慮基於棧的cocos2d::Vector<T>優先用於基於堆的
  • 當將cocos2d::Vector<T>作爲參數傳遞時,將它聲明成常量引用:const cocos2d::Vector<T>&
  • 返回值是cocos2d::Vector<T>時,直接返回值,這種情況下編譯器會優化成移動操作。
  • 不要用任何沒有繼承cocos2d::Object的類型作爲cocos2d::Vector<T>的數據類型。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章