慎用C++ std::map 的[]运算符

原创 2008年09月18日 13:48:00
map的[]运算符在用法上和我们对[]常规理解大有出入,因此也往往很容易造成了使用上的失误,在这点上我强烈认为stl设计犯了大错。
首先看其函数声明:
T& operator[] ( const key_type& x );
http://www.cplusplus.com/reference/stl/map/operator[].html 的描述中,该声明等效于:
(*((this->insert(make_pair(x,T()))).first)).second
倏忽的程序员一不留意就会栽入陷阱,因为在我们的常规理解里,[]操作不应该对本不属于容器自己的关键字做查询操作。但
map却直接执行了一次insert操作。
看以下代码:
#include <iostream>#include <map>using namespace std;class MapManager{public :    typedef map<string, string> MapNameToID;    string ret(const string& name)    {        return m_map[name];    }    void list()    {        for (   MapNameToID::iterator iter = m_map.begin();                iter != m_map.end();                ++iter)        {            cout << "(" << iter->first << ", " << iter->second << ")" << endl;        }    }private :    MapNameToID m_map;};int main(){    MapManager m;    cout << m.ret("yao") << endl;    cout << m.ret("jian") << endl;    m.list();    return 0;}
类MapManager的设计者本来希望通过ret(int index)查找关键字的值,但显然设计者这么做实际上不小心给map加入了新元素
当然,疏忽的地方在于,对于查询函数,应该加上const保护类成员,这样至少会编译错误。也就是说,压根在这里就不该
使用[]重载,而是应该用find,当然,如果find之前没有先判断该key是否存在,那么查询不存在的key将导致运行时错误。
或许[]重载正是为了保护查询不存的key时,不会出现运行时错误而选择了insert操作,但这样似乎也不是好办法。
正确写法:
#include <iostream>#include <map>using namespace std;class MapManager{public :    typedef map<string, string> MapNameToID;    string ret(const string& name) const // 加const    {        MapNameToID::const_iterator iterRs = m_map.find(name);        if (m_map.end() != iterRs)        {               return iterRs->second; // 用find(name)->second;        }        else        {               return "";        }    }    void list()    {        for (   MapNameToID::iterator iter = m_map.begin();                iter != m_map.end();                ++iter)        {            cout << "(" << iter->first << ", " << iter->second << ")" << endl;        }    }private :    MapNameToID m_map;};int main(){    MapManager m;    cout << m.ret("yao") << endl;    cout << m.ret("jian") << endl;    m.list();    return 0;}


另外,说说另一个用法:


#include <iostream>#include <map>using namespace std;class K{public :    K()    {        cout << "K()" << endl;    }    K(int)    {        cout << "K(int)" << endl;    }};int main(){    map<int, K> mp;    K k;    mp[1] = K(3);    //mp.insert(map<int, K>::value_type(1, K(3)));    return 0;}
以上代码输出是:
K()
K()
K(int)
而直接用被注释掉的insert的话输出是:
K()
K(int)

这里存在的效率差别我就不多说了。
总之,map的[]重载确实给我们带来了编码上感性上的便利,但总体而言,对于讲究效率和代码质量的程序员,似乎就不那么
推荐使用了。

入门计划->学用stl std::map<std::string, int>

C++:一种比较流行的强大功能面向对象编程语言,应用和前景都很广阔。stl:C++标准模板库,功能极其强大,将其完全掌握后C++编程会相当容易。map:一种关系式容器,可以根据关键字匹配多种数据。st...
  • awzzz
  • awzzz
  • 2003年08月27日 20:57
  • 7138

std::map用法

std::map用法    STL是标准C++系统的一组模板类,使用STL模板类最大的好处就是在各种C++编译器上都通用。    在STL模板类中,用于线性数据存储管理的类主要有vec...
  • TXH0001
  • TXH0001
  • 2011年03月12日 13:40
  • 75037

std::map 如何插入键值对

有两种方式,可以把数据放入map容器: 1.map[键] = 值;直接赋值。 这种方式:当要插入的键存在时,会覆盖键对应的原来的值。如果键不存在,则添加一组键值对。 2.map.insert().这是...
  • u011417605
  • u011417605
  • 2016年03月14日 09:48
  • 2547

std::map::erase的用法及陷阱

方法一: std::map mapTest; bool TestVal(const std::string & val); ...... std::map::iterator it = mapTe...
  • weiyuefei
  • weiyuefei
  • 2016年04月14日 20:24
  • 583

std::map::erase的用法及陷阱

方法一: [cpp] view plaincopy std::map mapTest;   bool TestVal(const std::string & val);    ...
  • zhangyueweia
  • zhangyueweia
  • 2015年12月14日 14:00
  • 2006

STL中std::map用法详解

原文:http://www.yitsoft.com/chap_study/ch_00029/ch_00029.asp std::map mapStudent; 1. map的构造函数 m...
  • tangketan
  • tangketan
  • 2012年06月26日 01:09
  • 3238

C++中std::map的使用

C++中std::map的使用
  • fengbingchun
  • fengbingchun
  • 2016年07月30日 18:38
  • 2549

C++学习 std::map介绍

给出了map的基本用法如插入、查找、删除、遍历等等,同时告诉你如何实现双键map,包括  (1) 只有两个键都匹配才命中目标 (2) 两个键中任意一个匹配就命中目标 可以扩展到多键 (...
  • skdkjxy
  • skdkjxy
  • 2015年02月03日 20:16
  • 3131

STL中map实现技术

红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. ...
  • Fandywang_jlu
  • Fandywang_jlu
  • 2008年03月23日 08:52
  • 14605

std::map的机制

转自 http://blog.csdn.net/solstice/article/details/8521946 陈硕 (chenshuo.com) 2013-01-20 std::...
  • messiran10
  • messiran10
  • 2016年07月30日 14:01
  • 1081
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:慎用C++ std::map 的[]运算符
举报原因:
原因补充:

(最多只允许输入30个字)