注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

map系列及LIST使用(含智能指针)  

2014-05-05 11:21:52|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

map系列及LIST使用(含智能指针)

最近对标准库中的一些map的相关数据结构mapunordered_maphash_map进行了一些对比和分析。并且对在maplist中使用智能指针进行了一些相关的测试。

其中hash_map属于标准库的扩展,在新的C++1X中,不再建议使用,这里也就不再对其进行说明,如果大家有兴趣可以自己在网上查找一些资料。

map系列中,因为重载了运算符[],所以很多人都喜欢使用类似数组的操作方式来操作其中的数据,一般如下:

插入: _testMap0[1] = “ert”;   _testMap1[“test”] = 100;

使用:int t0 = _testMap1[“test”];

殊不知这里面有很大的问题在其中,首先说使用的时候,这么用本身就用一个非常不好的方面,举个例子在上面的testMap1中,如果只有test这个KEY值和一个VALUE 100。那么在使用时int t0 = _testMap1[“test”];基本是没有问题的。但是如果在一些判断语句中:

                 If (3 == _testMap1[“ok”]){…..}

这时候你在断点里查看,会发现, _testMap1的数量从一个变成了两个,也就是说,如果你使用[]操作符,如果MAP系列中没有相应的KEY值,会直接插入这个KEY,并赋值给他一个默认的值,一般来说int 0,指针为nullptr NULL。这一般来说不是人们想要的,而且关键是没有提醒你,用得不熟悉的人自然会中了招。

另外,上面说这样用基本是没有问题的,说明还是有问题的,从目前的个人经验以及网上的相关经验发现,在某些情况下(并发和读写频繁的情况下)无论是MAP系列还是LIST中的REMOVE,都会偶尔有莫名崩溃的现象。所以建议大家尽量不要使用[]这个重载的操作运算符。那么不使用它,使用哪一个呢? 分两种情况:

插入:用insert函数:

_hashClient.insert(std::pair<SOCKET, std::shared_ptr<ClientData>>(pcd->Socket, pcd));

查找用find函数:

         HashMapSocket::const_iterator csit = _hashClient.find(s);

         if (_hashClient.end() != csit)

         {

                   return csit->second;

         }

 

一些资料:

http://blog.csdn.net/smuggler_2003/article/details/5099516

http://hi.baidu.com/hehehehello/item/c7c2bc44c9a3f0adde2a9f7c

http://bbs.csdn.net/topics/360158150

特别是在第三个博客中,使用的方法,不要使用指针的方式来操作MAP中的实际的值,或者这样说,MAP中比如存入的是一个结构体,但你得到的是一个结构体的指针,那么这样操作是非常危险的。

Client clientdata;

_testmap[0] = clientdata;

Client* = it;(*it clientdata,it是迭代器)

这种情况下可能在解锁后,数据内容会被改写,删除或者修改,这个锁的作用达不到效果的原因就在这

http://fpcfjf.blog.163.com/blog/static/55469793201161210538873/

http://fpcfjf.blog.163.com/blog/static/55469793201152093256309/

在上面的两个博客里,提到过listremove,为什么不建议大家使用这个函数呢,这个函数的主要缺点是他要做一个全表的遍历,也就是说,删除的时候儿会从头到尾把符合情况的都删除,而建议使用的erase这个函数则不会。这样,在数据量比较大并且重复数据较多的时候儿,前者的时间级数会大幅增加。而且在不断的遍历删除过程中会使迭代器不断的失效,容易引起崩溃。这个最上面的三个BLOG中也提到了。其中有一个就是把remove改成了erase后就自然消失了这种现象。

然后再说智能指针在这两类模板函数里使用,有一个非常好的用处,就不用自己再对内存进行管理了。而且经过测试在eraseremove后,如果智能指针没有人使用了并且过了生存范围(这个一定要记清,要出了生存范围),就自动调用析构或者说delete函数释放空间。

HashMapSocket g_hms;

ClientDataList g_cdl;

//测试智能指针的释放

void MTestRemoveErase_ptr()

{

         //MAP

         std::shared_ptr<ClientData> pTemp0 = std::make_shared<ClientData>();

         pTemp0->Port = 1000;

         pTemp0->Sip = "127.0.0.1";

         pTemp0->Socket = 1024;

         std::shared_ptr<ClientData> pTemp1 = std::make_shared<ClientData>();

         pTemp1->Port = 1001;

         g_hms[678] = pTemp0;

         g_hms[689] = pTemp1;

 

         if (67 == g_hms[1200]->Socket)

         {

         }

 

         if (nullptr == g_hms[1200])

         {

                   if (NULL == g_hms[1200])

                   {

                            int t = 9;

                   }

                  

         }

        

         //list

         std::shared_ptr<ClientData> pTemp2 = std::make_shared<ClientData>();

         pTemp2->Port = 1002;

         std::shared_ptr<ClientData> pTemp3 = std::make_shared<ClientData>();

         pTemp3->Port = 1007;

         g_cdl.push_back(pTemp2);

         g_cdl.push_back(pTemp3)

}

void MTestLen()

{      

         MTestRemoveErase_ptr();

         //del

         g_hms.erase(678);//此处智能指针在内存中可看到全空下面亦如此

         for (auto &p : g_cdl)

         {

                   p->Port = 1009;

                   g_cdl.remove(p);

                   break;

         }

}

还有一件事,erase有三个重载函数,可以适用于单个,列表和范围内使用,非常好用。

http://www.cnblogs.com/cutepig/archive/2007/07/15/819013.html

http://blog.csdn.net/wangwenwen/article/details/7583986

下面的这个BLOG是性能测试:

http://blog.chinaunix.net/uid-20384806-id-3055333.html

一般来说mapLOG(N)unordered_map是常数,hash_map这里就是打酱油了。

  评论这张
 
阅读(567)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017