寒星轩

There are innumerable stars in the sky, the smallest is me!

用户操作
[即时聊天] [发私信] [加为好友]
李星ID:starlee
206966次访问,排名341好友61人,关注者104
欢迎大家访问我的Blog。
主要是C++,设计模式,面向对象设计方面的技术文章。
starlee的文章
原创 98 篇
翻译 0 篇
转载 45 篇
评论 331 篇
李星的公告
郑重声明

        本BLOG所发表的 原创文章,作者保留一切权利。必须经过作者本人同意后方可转载,并注名作者(StarLee)和出处(CSDN Blog)。
作者Email:
coolstarlee(at)sohu.com
最近评论
陈诚:好象不一样,我这个共两个类,实现类和接口类
深夜才走在路上:实际上使用CLR封送C++类让人很受伤,在mc中有很多C++的特性不能使用,甚至STL都不可用
hfg :错了错了,当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

不管基类的析构函数是不是virtual ,派生类的析构函数还是会被调用的,区别只是在于基类的析构函数有没有被调用
Forrest Yu:Star Lee:

如果有两个以上的类需要包装,那又应该怎样做呢?
Forrest Yu:CLR 还是很强大的,
一些老的MFC项目可以先手动添加
#include <afx.h>,
其他的可能要加
#include <windows.h>,
然后再用这种方法.
文章分类
收藏
相册
友情链接
houdy的专栏
lijgame的专栏
lyrebing的专栏
禾青谷
存档
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 小心使用STL中map的[]操作符收藏

新一篇: 战争中的世外桃源--《欢迎来到东莫村》观后感 | 旧一篇: 你是许三多还是成才?--《士兵突击》观后感

    一个map就是一个(关键码(key),值(value))对偶的序列,它提供基于关键码的快速提取操作。也就是说,可以用下标运算符[]将关键码作为下标去执行查找,并返回对应的值。因此可以把map的使用方法想象成有特殊下标的数组。在很多时候用下标运算符[]来对map中的元素进行存取是非常方便和简单的;但是,如果map下标运算符[]运用不得当,也会造成意想不到的问题。
    我们知道,C++是不检查下标越界的。用超出数组下标范围的下标去访问数组元素的错误会在运行期出现,很有可能将程序搞崩溃。对于map而言,也没有类似的下标越界概念,但是却有作为下标的关键码(key)在map中不存在的现象。在这种情况下,如果运用不得当,就造成意想不到的问题,而且这种问题是属于比较隐蔽的问题。如果对map的下标运算符[]不是非常了解,将很难发现问题所在。
    比如说有下面的代码片断:

// 定义一个map
map<stringstring> mapTelDir;

// 用[]操作符可以方便快速的给map添加内容
mapTelDir["StarLee"= "13813131313";

// ...

// 修改关键码为LiXing的值
// 注意,这里的关键码在map里面并不存在
if (mapTelDir["LiXing"== "13913131313")
{
    mapTelDir[
"LiXing"= "13513131313";
}

// ...

// 输出
cout << "The cellhone number of LiXing is: " << mapTelDir["LiXing"<< endl;

     上面的代码看起来似乎没有任何问题,但是,最后一行的输出的手机号码却永远为空!原因就是在判断语句里面对map的下标运算符[]的错误使用。
    map的下标运算符[]的作用是:将关键码作为下标去执行查找,并返回对应的值;如果不存在这个关键码,就将一个具有该关键码和值类型的默认值的项插入这个map。
    对于上面的代码来说,if (mapTelDir["LiXing"] == "13913131313")这行代码首先去查询map中是否有关键码为LiXing的项,结果发现没有该项,于是就向map中插入了一项<"LiXing", "">(sting的默认值为空字符串)。这就造成if语句的判断结果永远为false,那样就不可能修改修改关键码为LiXing的值。
    为了更好的说明这个问题,可以看一下map下标运算符[]的实现代码:

// 下面的代码摘自VS2005中的..vcincludemap
mapped_type& operator[](const key_type& _Keyval)
    {    
// find element matching _Keyval or insert with default mapped
        iterator _Where = this->lower_bound(_Keyval);
        
if (_Where == this->end()
            
|| this->comp(_Keyval, this->_Key(_Where._Mynode())))
            _Where 
= this->insert(_Where,
                value_type(_Keyval, mapped_type()));
    
return ((*_Where).second);
    }

    map的下标操作符[]使用上面的方法定义,使向map里插入值和使用关键码来访问相应的值变得非常方便而快速。虽然在使用的时候会出现有人写出类似上面那样的错误代码,但是这是程序员的错误,因为写出正确的代码是程序员的责任。这样做很符合C++的风格:非常灵活,但是要小心使用。

发表于 @ 2008年04月07日 09:26:00|评论(loading...)|编辑

新一篇: 战争中的世外桃源--《欢迎来到东莫村》观后感 | 旧一篇: 你是许三多还是成才?--《士兵突击》观后感

评论

#nscboy 发表于2008-04-07 13:39:26  IP: 58.246.22.*
既然你的逻辑错掉了.你就别指望有正确的结果.
这不是map的错.
既然mapTelDir["LiXing"]没有被赋值.你就无法从mapTelDir得到这个键的值.
你得到的将是string().而这正是应该被期待的值.
2008-04-07 16:24:57作者回复
我并没有说map这样做有什么不对,我只是提醒一下大家在开发的时候注意map的[]操作符,别用错了。
#QuickGo 发表于2008-04-07 16:50:10  IP: 192.232.69.*
这个。。。
看了半天,怎么感觉和我预期的结果没有什么偏差?
#annywoody 发表于2008-04-08 10:38:54  IP: 58.16.16.*
这个应该都知道的吧。。。
#yang 发表于2008-04-08 14:16:44  IP: 221.221.55.*
你好, 在之前的文章"一步一步创建VC2005解决方案"中想请教你个问题. 在这篇文章中提到了一个批处理文件,我不知道这个文件具体该怎么用,用文章提到的方法,也就是用visual studio 2005 command prompt 运行该文件,可是我试的结果确是无法运行这个dat 文件,不知道这是怎么回事,望不吝赐教!
#homonia 发表于2008-04-09 09:21:27  IP: 211.69.198.*
Your work is very useful for me!
Thank you!
#21bird 发表于2008-04-09 10:56:32  IP: 60.219.138.*
虽然这样确实为空,可这样用和不这样用的结果是不是不太一样呢?

那个元素为空,和那个元素不存在 是不同的……

就是说,是不是这样:
如果这样用,就会多出个内容为空的元素。
如果不这样用,就不会多出那个空元素……

啊~大家有没有看晕啊?哈哈
#tttttttttttttttttttttttttttttttt 发表于2008-04-09 15:58:57  IP: 220.231.201.*
effective stl里面说了
#lll 发表于2008-04-10 09:21:40  IP: 125.34.46.*
if (mapTelDir["LiXing"] == "13913131313")
{
mapTelDir["LiXing"] = "13513131313";
}

如是,LZ的逻辑错误,mapTelDir["LiXing"]导致为空,
LZ提前执行一下“mapTelDir["LiXing"] = "13913131313"”,后面就不为空了,哈哈
#lsfbad 发表于2008-04-10 09:33:31  IP: 116.1.35.*
楼主的意思是
那样用的话,map就会新增一个元素,只是值是空的。

而本来的用意只是用来做简单判断,不想新增元素。

好文章。
发表评论  


登录
Csdn Blog version 3.1a
Copyright © 李星