深入理解Cocos2d-x 3.x:内置数据结构(2)Map

其实最没意思的数据结构就是Map和Vector这两个了,完完全全就是std::map和std::vector上面再加了一层引用计数。当然,这也有好处,就是支持std算法以及支持Cocos2d-x的内存管理机制。

看源码可以知道(下均只对Map进行分析,Vector同理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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派生出来的数据类型,这样才能支持内存管理机制,下面是构造函数(有多个构造函数,只列举了一个)

1
2
3
4
5
6
7
/** 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,检测通过。如果不是,会在编译期就告诉我们,这个地方编译不过。

接下来就是插入函数

1
2
3
4
5
6
7
8
9
10
11
12
/** @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的强引用

接下来是删除函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/** @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表示删除失败。

还有一些有意思的函数,如下这个

1
2
3
4
5
6
7
8
9
10
11
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增加一个随机数的长度,返回这个长度的迭代器。


感谢本文笔者NxShow的分享,Cocos引擎中文官网欢迎更多的开发者分享开发经验。来稿请发送至:support@cocos.org    

来源网址:http://blog.csdn.net/nxshow/article/details/44750235


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值