Cocos2d-x 3.0-Vector&map&value
在做Cocos2d-x2.0人的人们估计正在使用CCArray,CCDirectionary,CCDouble,CCFloat这些正搞得很爽,但不得不说 它们在V3.0中不用了。 看下3.0中的数据结合类Vector,Map,Value(建议大家自行阅读源码,本文只介绍如何使用,关于引用计数的概念推荐大家看我的视频), 以下案例来自TestCpp: void TemplateVectorTest::onEnter() { UnitTestDemo::onEnter(); Vector<Node*> vec;//定义一个向量,其实是对stl Vector的封装,只是加入了对象的内存计数管理 CCASSERT(vec.empty(),""); CCASSERT(vec.capacity() ==0,""); CCASSERT(vec.size() ==0,""); CCASSERT(vec.max_size() >0,""); auto node1 = Node::create(); node1->setTag(1); vec.pushBack(node1);//在向量添加一个元素 CCASSERT(node1->getReferenceCount() ==2,""); auto node2 = Node::create(); node2->setTag(2); vec.pushBack(node2);//添加元素 编号会从0开始 CCASSERT(vec.getIndex(node1) ==0,""); CCASSERT(vec.getIndex(node2) ==1,"");
auto node3 = Node::create(); node3->setTag(3); vec.insert(1,node3); //插入元素 CCASSERT(vec.at(0)->getTag() ==1,""); CCASSERT(vec.at(1)->getTag() ==3,""); CCASSERT(vec.at(2)->getTag() ==2,"");
// Test copy constructor Vector<Node*> vec2(vec); //复制一个向量 CCASSERT(vec2.size() == vec.size(),""); ssize_t size = vec.size(); for (ssize_t i =0; i < size; ++i) { CCASSERT(vec2.at(i) == vec.at(i),""); CCASSERT(vec.at(i)->getReferenceCount() ==3,""); CCASSERT(vec2.at(i)->getReferenceCount() ==3,""); }
// Test copy assignment operator Vector<Node*> vec3; vec3 = vec2; CCASSERT(vec3.size() == vec2.size(),""); size = vec3.size(); for (ssize_t i =0; i < size; ++i) { CCASSERT(vec3.at(i) == vec2.at(i),""); CCASSERT(vec3.at(i)->getReferenceCount() ==4,""); CCASSERT(vec2.at(i)->getReferenceCount() ==4,""); CCASSERT(vec.at(i)->getReferenceCount() ==4,""); }
// Test move constructor (Lambda 表达式,定义一个函数用于创建一个Vector,关于Lambda建议看我的视频) auto createVector = [this](){ Vector<Node*> ret; for (int i =0; i < 20; i++) { ret.pushBack(Node::create()); } int j = 1000; for (auto& child : ret) { child->setTag(j++); } return ret; }; Vector<Node*> vec4(createVector()); for (const auto& child : vec4) { CC_UNUSED_PARAM(child); CCASSERT(child->getReferenceCount() ==2,""); }
// Test init Vector<T> with capacity Vector<Node*> vec5(10); CCASSERT(vec5.capacity() ==10,""); vec5.reserve(20); CCASSERT(vec5.capacity() ==20,"");
CCASSERT(vec5.size() ==0,""); CCASSERT(vec5.empty(),"");
auto toRemovedNode = Node::create(); vec5.pushBack(toRemovedNode); CCASSERT(toRemovedNode->getReferenceCount() ==2,"");
// Test move assignment operator vec5 = createVector(); CCASSERT(toRemovedNode->getReferenceCount() ==1,""); CCASSERT(vec5.size() ==20,"size should be 20");
for (constauto& child : vec5) //这也是C++11新特性,好用吧,不像STL用迭代器那么麻烦 { CC_UNUSED_PARAM(child); CCASSERT(child->getReferenceCount() ==2,""); }
// Test Vector<T>::find CCASSERT(vec.find(node3) == (vec.begin() +1),""); CCASSERT(std::find(std::begin(vec),std::end(vec),node2) == (vec.begin() +2),"");
CCASSERT(vec.front()->getTag() ==1,""); CCASSERT(vec.back()->getTag() ==2,"");
CCASSERT(vec.getRandomObject(),""); CCASSERT(!vec.contains(Node::create()),""); CCASSERT(vec.contains(node1),""); CCASSERT(vec.contains(node2),""); CCASSERT(vec.contains(node3),""); CCASSERT(vec.equals(vec2),""); CCASSERT(vec.equals(vec3),"");
// Insert vec5.insert(2,node1); CCASSERT(vec5.at(2)->getTag() ==1,""); CCASSERT(vec5.size() ==21,""); vec5.back()->setTag(100); vec5.popBack(); CCASSERT(vec5.size() ==20,""); CCASSERT(vec5.back()->getTag() !=100,"");
// Erase and clear Vector<Node*> vec6 = createVector(); Vector<Node*> vec7 = vec6;// Copy for check
CCASSERT(vec6.size() ==20,""); vec6.erase(vec6.begin() +1); // CCASSERT(vec6.size() ==19,""); CCASSERT((*(vec6.begin() +1))->getTag() == 1002,""); vec6.erase(vec6.begin() +2,vec6.begin() + 10); CCASSERT(vec6.size() ==11,""); CCASSERT(vec6.at(0)->getTag() ==1000,""); CCASSERT(vec6.at(1)->getTag() ==1002,""); CCASSERT(vec6.at(2)->getTag() ==1011,""); CCASSERT(vec6.at(3)->getTag() ==1012,""); vec6.erase(3); CCASSERT(vec6.at(3)->getTag() ==1013,""); vec6.eraSEObject(vec6.at(2)); CCASSERT(vec6.at(2)->getTag() ==1013,""); vec6.clear();
auto objA =Node::create();// retain count is 1 auto objB = Node::create(); auto objC = Node::create(); { Vector<Node*> array1; Vector<Node*> array2;
// push back objA 3 times array1.pushBack(objA); // retain count is 2 array1.pushBack(objA); // retain count is 3 array1.pushBack(objA); // retain count is 4
array2.pushBack(objA); // retain count is 5 array2.pushBack(objB); array2.pushBack(objC);
for (auto obj : array1) { array2.eraSEObject(obj); } CCASSERT(objA->getReferenceCount() ==4,""); } CCASSERT(objA->getReferenceCount() ==1,""); { //这是一个代码块,出了块引用计数会恢复,是一个AutoReleasePool Vector<Node*> array1; // push back objA 3 times array1.pushBack(objA); // retain count is 2 array1.pushBack(objA); // retain count is 3 array1.pushBack(objA); // retain count is 4 CCASSERT(objA->getReferenceCount() ==4,""); array1.eraSEObject(objA,true); // Remove all occurrences in the Vector. CCASSERT(objA->getReferenceCount() ==1,"");
array1.pushBack(objA); // retain count is 2 array1.pushBack(objA); // retain count is 3 array1.pushBack(objA); // retain count is 4
array1.eraSEObject(objA, false); CCASSERT(objA->getReferenceCount() ==3,"");// Only remove the first occurrence in the Vector. }
// Check the retain count in vec7 CCASSERT(vec7.size() ==20,""); for (const auto& child : vec7) { CC_UNUSED_PARAM(child); CCASSERT(child->getReferenceCount() ==2,""); }
// Sort 排序,结合Lambda Vector<Node*> vecForSort = createVector(); std::sort(vecForSort.begin(),vecForSort.end(),[](Node* a,Node* b){ return a->getTag() >= b->getTag(); });
for (int i = 0; i < 20; ++i) { CCASSERT(vecForSort.at(i)->getTag() -1000 == (19 - i),""); }
// Reverse vecForSort.reverse(); for (int i = 0; i < 20; ++i) { CCASSERT(vecForSort.at(i)->getTag() -1000 == i,""); }
// Swap Vector<Node*> vecForSwap = createVector(); vecForSwap.swap(2,4); CCASSERT(vecForSwap.at(2)->getTag() ==1004,""); CCASSERT(vecForSwap.at(4)->getTag() ==1002,""); vecForSwap.swap(vecForSwap.at(2),vecForSwap.at(4)); CCASSERT(vecForSwap.at(2)->getTag() ==1002,""); CCASSERT(vecForSwap.at(4)->getTag() ==1004,"");
// shrinkToFit Vector<Node*> vecForShrink = createVector(); vecForShrink.reserve(100); CCASSERT(vecForShrink.capacity() ==100,""); vecForShrink.pushBack(Node::create()); vecForShrink.shrinkToFit(); CCASSERT(vecForShrink.capacity() ==21,"");
// get random object // Set the seed by time srand((unsigned)time(nullptr)); Vector<Node*> vecForRandom = createVector(); log("<--- begin ---->"); for (int i = 0; i < vecForRandom.size(); ++i) { log("Vector: random object tag = %d",vecForRandom.getRandomObject()->getTag()); } log("<---- end ---->");
// Self assignment Vector<Node*> vecSelfAssign = createVector(); vecSelfAssign = vecSelfAssign; CCASSERT(vecSelfAssign.size() ==20,"");
for (const auto& child : vecSelfAssign) { CC_UNUSED_PARAM(child); CCASSERT(child->getReferenceCount() ==2,""); }
vecSelfAssign = std::move(vecSelfAssign); CCASSERT(vecSelfAssign.size() ==20,""); }
// const at Vector<Node*> vecConstAt = createVector(); constFunc(vecConstAt); }
//---------------------------以下是Map的使用-----------------------------------
void TemplateMapTest::onEnter() { UnitTestDemo::onEnter(); auto createMap = [this](){ Map<std::string,Node*> ret; for (int i =0; i < 20; ++i) { auto node = Node::create();
node->setTag(1000 + i); ret.insert(StringUtils::toString(i),node); }
return ret; }; // Default constructor Map<std::string,Node*> map1; CCASSERT(map1.empty(),""); CCASSERT(map1.size() ==0,""); CCASSERT(map1.keys().empty(),""); CCASSERT(map1.keys(Node::create()).empty(),""); // Move constructor Map<std::string,Node*> map2 = createMap(); for (const auto& e : map2) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==2,""); } // Copy constructor Map<std::string,Node*> map3(map2); for (const auto& e : map3) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==3,""); } // Move assignment operator Map<std::string,Node*> map4; auto unusedNode = Node::create(); map4.insert("unused",unusedNode); map4 = createMap(); CCASSERT(unusedNode->getReferenceCount() ==1,""); for (const auto& e : map4) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==2,""); } // Copy assignment operator Map<std::string,Node*> map5; map5 = map4; for (const auto& e : map5) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==3,""); } // Check size CCASSERT(map4.size() == map5.size(),""); for (const auto& e : map4) { CC_UNUSED_PARAM(e); CCASSERT(e.second == map5.find(e.first)->second,""); } // bucket_count,bucket_size(n),bucket log("--------------"); log("bucket_count = %d",static_cast<int>(map4.bucketCount())); log("size = %d",static_cast<int>(map4.size())); for (int i = 0; i < map4.bucketCount(); ++i) { log("bucket_size(%d) = %d",i,static_cast<int>(map4.bucketSize(i))); } for (const auto& e : map4) { log("bucket("%s"),bucket index = %d",e.first.c_str(),static_cast<int>(map4.bucket(e.first))); } log("----- all keys---------"); // keys and at auto keys = map4.keys(); for (const auto& key : keys) { log("key = %s",key.c_str()); }
auto node10Key = map4.at("10"); map4.insert("100",node10Key); map4.insert("101",node10Key); map4.insert("102",node10Key);
log("------ keys for object --------"); auto keysForObject = map4.keys(node10Key); for (const auto& key : keysForObject) { log("key = %s",key.c_str()); } log("--------------");
// at in const function constFunc(map4);
// find auto nodeToFind = map4.find("10"); CC_UNUSED_PARAM(nodeToFind); CCASSERT(nodeToFind->second->getTag() ==1010,"");
// insert Map<std::string,Node*> map6; auto node1 = Node::create(); node1->setTag(101); auto node2 = Node::create(); node2->setTag(102); auto node3 = Node::create(); node3->setTag(103); map6.insert("insert01",node1); map6.insert("insert02",node2); map6.insert("insert03",node3);
CCASSERT(node1->getReferenceCount() ==2,""); CCASSERT(node2->getReferenceCount() ==2,""); CCASSERT(node3->getReferenceCount() ==2,""); CCASSERT(map6.at("insert01") == node1,""); CCASSERT(map6.at("insert02") == node2,""); CCASSERT(map6.at("insert03") == node3,"");
// erase Map<std::string,Node*> mapForErase = createMap(); mapForErase.erase(mapForErase.find("9")); CCASSERT(mapForErase.find("9") == mapForErase.end(),""); CCASSERT(mapForErase.size() ==19,"");
mapForErase.erase("7"); CCASSERT(mapForErase.find("7") == mapForErase.end(),""); CCASSERT(mapForErase.size() ==18,"");
std::vector<std::string> itemsToRemove; itemsToRemove.push_back("2"); itemsToRemove.push_back("3"); itemsToRemove.push_back("4"); mapForErase.erase(itemsToRemove); CCASSERT(mapForErase.size() ==15,"");
// clear Map<std::string,Node*> mapForClear = createMap(); auto mapForClearCopy = mapForClear; mapForClear.clear();
for (const auto& e : mapForClearCopy) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==2,""); }
// get random object // Set the seed by time srand((unsigned)time(nullptr)); Map<std::string,Node*> mapForRandom = createMap(); log("<--- begin ---->"); for (int i = 0; i < mapForRandom.size(); ++i) { log("Map: random object tag = %d",mapForRandom.getRandomObject()->getTag()); } log("<---- end ---->");
// Self assignment Map<std::string,Node*> mapForSelfAssign = createMap(); mapForSelfAssign = mapForSelfAssign; CCASSERT(mapForSelfAssign.size() ==20,"");
for (const auto& e : mapForSelfAssign) { CC_UNUSED_PARAM(e); CCASSERT(e.second->getReferenceCount() ==2,""); }
mapForSelfAssign = std::move(mapForSelfAssign); CCASSERT(mapForSelfAssign.size() ==20,""); } }
//--------------------------以下是Value的使用,它完成基本数据类型到对象的包装--------
void ValueTest::onEnter() { UnitTestDemo::onEnter();
Value v1; CCASSERT(v1.getType() ==Value::Type::NONE,""); CCASSERT(v1.isNull(),"");
Value v2(100); CCASSERT(v2.getType() ==Value::Type::INTEGER,""); CCASSERT(!v2.isNull(),"");
Value v3(101.4f); CCASSERT(v3.getType() ==Value::Type::FLOAT,""); CCASSERT(!v3.isNull(),"");
Value v4(106.1); CCASSERT(v4.getType() ==Value::Type::DOUBLE,""); CCASSERT(!v4.isNull(),"");
unsigned char byte =50; Value v5(byte); CCASSERT(v5.getType() ==Value::Type::BYTE,""); CCASSERT(!v5.isNull(),"");
Value v6(true); CCASSERT(v6.getType() ==Value::Type::BOOLEAN,""); CCASSERT(!v6.isNull(),"");
Value v7("string"); CCASSERT(v7.getType() ==Value::Type::STRING,""); CCASSERT(!v7.isNull(),"");
Value v8(std::string("string2")); CCASSERT(v8.getType() ==Value::Type::STRING,""); CCASSERT(!v8.isNull(),"");
auto createValueVector = [&](){ ValueVector ret; ret.push_back(v1); ret.push_back(v2); ret.push_back(v3); return ret; };
Value v9(createValueVector()); CCASSERT(v9.getType() ==Value::Type::VECTOR,""); CCASSERT(!v9.isNull(),"");
auto createValueMap = [&](){ ValueMap ret; ret["aaa"] = v1; ret["bbb"] = v2; ret["ccc"] = v3; return ret; };
Value v10(createValueMap()); CCASSERT(v10.getType() ==Value::Type::MAP,""); CCASSERT(!v10.isNull(),"");
auto createValueMapIntKey = [&](){ ValueMapIntKey ret; ret[111] = v1; ret[222] = v2; ret[333] = v3; return ret; };
Value v11(createValueMapIntKey()); CCASSERT(v11.getType() ==Value::Type::INT_KEY_MAP,""); CCASSERT(!v11.isNull(),""); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |