Cocos2dx 3.0 過渡篇(三十一)ValueVector和Vector不得不說的故事,cocos2dxvector

來源:互聯網
上載者:User

Cocos2dx 3.0 過渡篇(三十一)ValueVector和Vector不得不說的故事,cocos2dxvector

本文投票地址:http://vote.blog.csdn.net/Article/Details?articleid=37834689

前天看到一個頗為糾結的選擇題:有一天你遇到一個外星人,這時外星人很熱情的邀請你到他們星球去玩,你如何選

1:去,但是你有可能永遠不能在回來。
2:不去,但是外星人會消去你的記憶

這問題很刺激有木有?! 看似簡單的一個問題,不同的答案卻隱藏著不同的含義。
------------------
魚與熊掌不可兼得,類似這種例子生活中會經常碰到。同樣的,如果你有去瞭解過Cocos2dx3.0,也會遇到這樣一個令人糾結的情況:
那就是: Value 與 Vector(Map)。
為什麼這麼說呢?且聽我慢慢道來。
-----------------

在Cocos2dx 2.0版本,
我們要儲存一個int型資料,應該放到哪裡?沒錯,放到 CCArray中,如下:
int i = 10;CCArray _array = CCArray::create();//建立一個CCArray數組_array->addObject(CCInteger::create(i));//將int型資料放入數組中
如果要儲存一個CCObject對象,又是用什麼存呢?是的,又是 CCArray
CCSprite* sp = CCSprite::create("star.png");//建立一個精靈..._array->addObject(sp);//將精靈放入到數組中

在Cocos2dx3.0版本,
我們都知道該版本的 CCArray已經被甩了(實際上用__Array也還是可以替用一下),那麼要儲存一個Ref(3.0後CCObject改名為Ref)對象應該如何操作?機智的我馬上想到了 CCArray的替代者:Vector,範例程式碼如下:
auto sp = Sprite::create("star.png");...Vector<Sprite*> sp_vec;//建立一個Sprite*類型的容器sp_vec.pushBack(sp);//將精靈放入到容器中
如果對Vector的操作不是很熟悉,可以看之前的部落格:http://blog.csdn.net/star530/article/details/19170853

接下來問題來了,如果要儲存一個資料類型,如int型資料,那麼用Vector可以實現嗎?答案是否定的,在Vector的官方說明文檔裡有這麼一句話:

cocos2d::Vector<T> 中的T必須是一個指向cocos2d::Ref子類對象的指標。不能是其他資料類型或者原生類型,因為我們已經將 Cocos2d-x 的記憶體管理模型整合到 cocos2d::Vector<T> 中。

有句話叫什麼來著: 上帝為你關上了一扇門,一定會為你開啟一扇窗...此處不留爺,自有留爺處...既然Vector容不下資料類型的元素,那麼肯定有可以替代它的東西存在。沒錯, ValueVector登上了曆史舞台。
第一次看到ValueVector時我就愣住了,這貨又是什麼碗糕?幾秒後我反應過來,這貨肯定是Value與Vector的私生子,我實在太特麼機智了,這麼抽象的命名都能讓我快速想到答案,心中不禁暗自得意。
先到CCValue.h標頭檔中看下它的聲明:
typedef std::vector<Value> ValueVector;
可以看出, ValueVector實際上就是一個存放Value類型元素的std::vector容器,這裡和我之前的猜測有些出入。下面將幾個int型資料存放區到ValueVector中。
int a = 10;int b = 20;ValueVector val_vec;val_vec.push_back(Value(a));val_vec.push_back(Value(b));

上面代碼就是建立兩個int型的變數,然後放入ValueVector中,其中要注意的是:因為ValueVector中只能存放Value類型的元素,所以int型的a、b變數必須轉換成Value類型後才能放入到ValueVector中。

關於Value的一些用法,可以看之前的部落格:http://blog.csdn.net/star530/article/details/21651751

------------------------------------------------------------------------------------------------------------

說到ValueVector,那就順便提下它的一些簡單操作:
1、讀取Plist(xml)設定檔
。如下:
ValueVector star_val = FileUtils::getInstance()->getValueVectorFromFile("star.plist");
不過用 ValueVector讀取的plist檔案只局限於是該plist的格式的以array數群組類型開頭的,例如下面這種:
<array><dict><key>name</key><string>star</string><key>isCool</key><string>yes</string></dict></array>
如果是以dict字典類型開頭的檔案,則要換用ValueMap,這是下一篇的內容,先跳過

2、往ValueVector中插入一個元素。上面有提到過,ValueVector實際上就是一個存放Value類型的vector順序容器,所以它的 插入元素方式可以直接使用vector順序容器的操作。樣本如下:
int a = 10;std::string b = "star is so cool";ValueVector star_val;star_val.push_back( Value(a) );star_val.push_back( Value(b) );//放入ValueVector前都要先將類型轉成Value類型

3、提取ValueVector中的元素。這裡我接上面的例子來用:
int a1 = star_val.at(0).asInt();std::string b1 = star_val.at(1).asString();CCLOG("a1 = %d ,b1 = %s",a1,b1);
上面的代碼比較容易理解,就是 提取star_val中放在0和1位置上的元素,然後分別轉成int型和string型。asInt()與asString()是Value用來實作類別型轉換的函數。

4、刪除ValueVector中的元素。
容器中比較常用的刪除元素方式有三種:
1)刪除容器中最後一個元素
star_val.pop_back();//直接刪除容器中最後一個元素
2)用erase刪除容器中的某一個元素?為什麼我要在前面加個問號呢?假設我要刪除star_val中的 元素a,代碼如下:
auto star_iter = std::find(star_val.begin(),star_val.end(),a);star_val.erase(star_iter);
上面兩行代碼資訊量還是比較大的,首先我們要知道erase 刪除的是由一個迭代器指向的單個元素,而不是直接這樣:
star_val.erase(a);

這種操作是錯誤的,那麼,什麼是迭代器呢?我舉個小例子:


假設一個教室就是一個vector容器,每個學生都是vector中的一個元素,而學生對應的座號就是迭代器。假設有一個新來的老師erase,她上課的時候你竟然和旁邊的女同學眉來眼去,老師大怒,她打算讓你立馬從教室中滾出去,但她根本不知道你的名字,所以她只能這樣做:

“第3列、第5排那個搞小動作的童鞋......別指了,說的就是你,你特麼給我滾出去”


好了,讓我們忘記這個麻辣女老師吧。既然已經知道erase裡的參數須是一個迭代器,那麼a元素對應的迭代器是什麼呢? 這裡就要用到find演算法,它將返回a在容器中的迭代器。(std::find的具體用法請猛戳這裡:點我!!!)
最後, 我不得不羞澀的告訴大家,這種刪除元素的方式是無法編譯成功的!!!因為Value裡沒有重載==運算子,而std::find裡面的資料類型必須實現==運算子,所以沒法用尋找,也就沒法刪除。
看到這裡有人肯定要拍桌子了:尼瑪,這方法不能刪除你寫這麼多幹嘛?褲子都脫了你就給我看這個?&……%*。
我的回答是: 呵呵...知道我當初折騰這個erase用了多少時間嗎?沒錯!我現在就是報複社會的節奏!不拿你們樂呵樂呵偶心裡不痛快~!

3)請收合手裡憤怒的西瓜刀,深吸一口氣。
既然無法刪除指定的元素,那我破罐子破摔,將全部元素都刪除總可以吧?答案是肯定的:
star_val.clear();
用clear刪除全部元素,從根源上解決您生理上的困擾~

-----------------------------------------------------------------------------------------------------------------------

好了,ValueVector的用法說到這裡,最後做下總結和補充:
1、Vector只能用來存放Ref類型的元素,不能存放資料類型的元素;
2、ValueVector只能用來存放Value類型的元素,因為Value說到底就是資料類型,所以也可以認為ValueVector只能用來存放資料類型,千萬別將Ref類型的元素放進入,否則會很刺激。
3、ValueVector中可以放ValueVector,前提是將ValueVector轉成Value類型;而Vector中不能存放Vector類型的元素,如下:

ValueVector star_val;ValueVector star_val2;star_val.push_back( Value(star_val2) );//正確Vector< Vector<Ref*> > star_vec;//錯誤!

OK,就寫到這裡吧。

----------------------------------------------------------------------------------------------------------------------

尊重原創,轉載請註明來源:http://blog.csdn.net/star530/article/details/37834689

本文參加了CSDN部落格大賽,如果你覺得該篇對你有所協助,請給我投上一票吧!我這輩子都會感激你的!投票地址:

http://vote.blog.csdn.net/Article/Details?articleid=37834689(拉倒頁面最下方即可投票




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.