其實最沒意思的數據結構就是Map和Vector這兩個了,完完全全就是std::map和std::vector上面再加了一層引用計數。當然,這也有好處,就是支持std算法以及支持cocos2d-x的內存管理機制。
看源碼可以知道(下均只對Map進行分析,Vector同理)
template <class K, class V>
class Map
{
public:
// ------------------------------------------
// Iterators
// ------------------------------------------
#if USE_STD_UNORDERED_MAP
typedef std::unordered_map<K, V> RefMap;
#else
typedef std::map<K, V> RefMap;
#endif
protected:
RefMap _data;
};
內部的數據結構就是一個std::unordered_map,但是cocos2d-x對其做了一個限制,V必須是由Ref派生出來的數據類型,這樣才能支持內存管理機制,下面是構造函數(有多個構造函數,只列舉了一個)
/** Default constructor */
Map<K, V>()
: _data()
{
static_assert(std::is_convertible<V, Ref*>::value, "Invalid Type for cocos2d::Map<K, V>!");
CCLOGINFO("In the default constructor of Map!");
}
static_assert是表示在編譯時檢查,std::is_convertible是檢測V與Ref*是否是繼承關係,如果是,value爲true,檢測通過。如果不是,會在編譯期就告訴我們,這個地方編譯不過。
接下來就是插入函數
/** @brief Inserts new elements in the map.
* @note If the container has already contained the key, this function will erase the old pair(key, object) and insert the new pair.
* @param key The key to be inserted.
* @param object The object to be inserted.
*/
void insert(const K& key, V object)
{
CCASSERT(object != nullptr, "Object is nullptr!");
erase(key);
_data.insert(std::make_pair(key, object));
object->retain();
}
值得注意的是,這裏先有一個刪除操作,再進行插入,這樣爲了保證所有的key都是唯一值,但是這樣會多造成一次遍歷,因爲unordered_map的插入是無序的,所以unordered_map的insert操作的複雜度是O(1),但是erase的刪除必須要find key,所以會有O(N)的複雜度,所以效率會比直接使用unordered_map低。
然後是retain,保持對V類型的object的強引用
接下來是刪除函數
/** @brief Removes an element with an iterator from the Map<K, V> container.
* @param k Key of the element to be erased.
* Member type 'K' is the type of the keys for the elements in the container,
* defined in Map<K, V> as an alias of its first template parameter (Key).
*/
size_t erase(const K& k)
{
auto iter = _data.find(k);
if (iter != _data.end())
{
iter->second->release();
_data.erase(iter);
return 1;
}
return 0;
}
首先find到K,然後先執行release,再刪除,返回1表示刪除成功,0表示刪除失敗。
還有一些有意思的函數,如下這個
V getRandomObject() const
{
if (!_data.empty())
{
ssize_t randIdx = rand() % _data.size();
const_iterator randIter = _data.begin();
std::advance(randIter , randIdx);
return randIter->second;
}
return nullptr;
}
函數的作用是返回一個隨機對象,首先判斷非空,然後獲取一個(0-data.size)的隨機數,使用std::advance給begin增加一個隨機數的長度,返回這個長度的迭代器。