【问题标题】:What happens if I read a map's value where the key does not exist?如果我读取不存在键的地图值会发生什么?
【发布时间】:2012-04-24 20:44:31
【问题描述】:
map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];

我很困惑,因为我不知道它是否被认为是未定义的行为,如何知道我何时请求一个不存在的密钥,我是否只使用 find 代替?

【问题讨论】:

    标签: c++ map


    【解决方案1】:

    map::operator[] 在数据结构中搜索与给定键对应的值,并返回对它的引用。

    如果找不到它,它会透明地为其创建一个默认构造元素。 (如果您不希望这种行为,您可以改用map::at 函数。)

    您可以在此处获取 std::map 方法的完整列表:

    http://en.cppreference.com/w/cpp/container/map

    这是当前 C++ 标准中map::operator[] 的文档...

    23.4.4.3 地图元素访问

    T&amp; operator[](const key_type&amp; x);

    1. 效果:如果map中没有与x等效的key,则将value_type(x, T())插入map中。

    2. 要求:key_type 应为 CopyConstructible,mapped_type 应为 DefaultConstructible。

    3. 返回:对 *this 中 x 对应的 mapped_type 的引用。

    4. 复杂度:对数。

    T&amp; operator[](key_type&amp;&amp; x);

    1. 效果:如果map中没有与x等效的key,则将value_type(std::move(x), T())插入map中。

    2. 要求:mapped_type 应为 DefaultConstructible。

    3. 返回:对 *this 中 x 对应的 mapped_type 的引用。

    4. 复杂度:对数。

    【讨论】:

    • 我实际上并没有在标准中找到它所说的任何地方。至少,不在 23.3.1.2 [lib.map.access] 或我记得要检查的任何其他地方。编辑:显然我正在查看标准的旧版本。我的错。
    • @VladCiobanu:以上是 23.4.4.3 逐字复制。您使用的是当前版本ISO/IEC 14882:2011(E)吗?
    【解决方案2】:

    如果您尝试使用索引运算符[] 访问key value,则可能会发生两件事:

    1. 地图包含此key。所以它会返回对应的key value
    2. 地图不包含key。在这种情况下,它会自动将key 添加到带有null value 的地图中。

    "pootoo" 键在您的地图中不存在。所以它会自动添加这个keyvalue = ""(空字符串)。你的程序将打印空字符串。

    这里的地图大小将增加1

    要搜索密钥,您可以使用map_name.find(),如果该密钥不存在,它将返回map_name.end()。并且不会添加额外的key

    当您想为某个键设置值时,可以使用[] 运算符。

    【讨论】:

      【解决方案3】:

      这不是未定义的行为。如果operator [] 没有为提供的键找到值,它会在该位置插入一个值。

      【讨论】:

      • 有帮助。 “它在那个位置插入一个。” - 如果地图不存在,它会增加 1 的大小。
      【解决方案4】:

      对于 operator[],如果你试图访问一个不存在的键的值,一个默认构造的新值对象将被放入映射中并返回它的引用。

      【讨论】:

        【解决方案5】:

        mapoperator[] 返回一个非常量引用,您可以按照第二行显示的方式使用它进行分配。以这种方式访问​​会创建一个value 类型的默认构造元素。

        如果你想找到一个find一个元素,更好的方法是

        iterator find ( const key_type& x )
        

        (或 const 替代方法)如果找不到密钥,或者您只想知道它是否在您可以使用的集合中,它将返回等于 &lt;map&gt;.end() 的迭代器

        size_type count ( const key_type& x ) const
        

        因为键是唯一的,所以它总是返回 1 或 0。

        【讨论】:

          【解决方案6】:

          如果运算符 [] 没有找到提供的键的值,它会在该位置插入一个值。

          但是你应该注意如果你访问not exist key并调用它的成员函数,比如mapKV[not_exist_key].member_fun()。程序可能会崩溃。

          举个例子,测试类如下:

          struct MapValue{
              int val;
          
              MapValue(int i=0){
                  cout<<"ctor: "<<i<<endl; val = i;
              }
          
              ~MapValue(){
                  cout<<"dtor: "<<val<<endl;
              }
          
              friend ostream& operator<<(std::ostream& out, const MapValue& mv){
                  cout<<"MapValue: "<<mv.val<<endl;
              }
          
              string toString(){
                  cout<<"MapValue: "<<val<<endl;
              }
          };
          

          测试代码:

          cout<<"-------create map<int, MapValue>-------"<<endl;
          
          map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};
          
          cout<<"-----cout key[2]-----"<<endl;
          cout<<idName[2]<<endl;
          
          cout<<"-----cout key[5]-----"<<endl;
          cout<<idName[5]<<endl;
          
          cout<<"------- runs here means, does't crash-------"<<endl;
          

          输出如下:

          -------create map<int, MapValue>-------
          ctor: 1
          ctor: 2
          dtor: 2
          dtor: 1
          dtor: 2
          dtor: 1
          -----cout key[2]-----
          MapValue: 2
          
          -----cout key[5]-----
          ctor: 0
          MapValue: 0
          
          -------runs here means, does't crash-------
          dtor: 0
          dtor: 2
          dtor: 1
          

          我们可以看到:idName[5] 调用 map 构造 {5, MapValue(0)} 插入到 idName。

          但是如果你通过idName[5]调用成员函数,那么程序就会崩溃:

          cout<<"-------create map<int, MapValue>-------"<<endl;
          
          map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};
          
          
          idName[5].toString();  // get crash here.
          
          
          cout<<"------- runs here means, doesn't crash-------"<<endl;
          

          【讨论】:

          • 它不应该崩溃,因为地图一定是其他错误
          【解决方案7】:

          请查看 out_of_range 异常: http://www.cplusplus.com/reference/stdexcept/out_of_range/

          如果 key 不存在,这就是 map::at 和 map::operator[] 将抛出的内容。您可以像链接中的矢量示例一样捕获它。

          您还可以使用: http://www.cplusplus.com/reference/map/map/find/

          然后检查 map::end

          【讨论】:

          • 不,只有 map::at 抛出,map::operator[] 如果键不存在则创建一个新的 value_type
          猜你喜欢
          • 1970-01-01
          • 2014-02-06
          • 2011-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多