【问题标题】:STL MAP should use find() or [n] identifier to find element in map?STL MAP 应该使用 find() 或 [n] 标识符在地图中查找元素?
【发布时间】:2012-05-14 11:04:23
【问题描述】:

我很困惑哪个更有效?

既然可以直接访问map,为什么还要使用find呢?

我只需要知道哪种方式更有效。

#include <iostream>
#include <map>
using namespace std;

int main ()
{
  map<char,int> mymap;
  map<char,int>::iterator it;

  mymap['a']=50;
  mymap['b']=100;
  mymap['c']=150;
  mymap['d']=200;

  //one way

  it=mymap.find('b');
  cout << (*it).second <<endl;

  //another way
      cout << mymap['b'] <<endl;

  return 0;
}

提前致谢! :)

【问题讨论】:

    标签: c++ stl map upperbound


    【解决方案1】:

    使用find 意味着如果键不存在,您不会无意中创建地图中的新元素,而且——更重要的是——这意味着您可以使用@ 987654322@ 来查找元素,如果你只有一个 constant 对地图的引用。

    这当然意味着你应该检查find的返回值。通常是这样的:

    void somewhere(const std::map<K, T> & mymap, K const & key)
    {
        auto it = mymap.find(key);
        if (it == mymap.end()) { /* not found! */ }
        else                   { do_something_with(it->second); }
    }
    

    【讨论】:

    • +1 当您不想创建未找到的元素时,这一点非常重要。
    【解决方案2】:

    既然可以直接访问map,为什么还要使用find呢?

    因为map&lt;&gt;::operator[] 有时很讨厌。如果元素不存在,则:

    • 它插入它
    • 值初始化它
    • 返回值的引用

    因此它总是返回一个有效的值引用,即使之前不存在一个键。这种行为不会多次发生。

    另一方面,map&lt;&gt;::find() 更安全;因为它返回end(),如果一个值没有退出。 find() 的另一个优点是它返回一个迭代器,其中包含对键 (first) 和值(second) 的引用。

    【讨论】:

    • operator[] 返回对值的引用,而不是键。
    • @jpalecek,是的,它被交换了。谢谢
    • map&lt;&gt;::find() 更安全。嗯,其实不是。最简单的例子是问题中的代码,用户没有验证迭代器是否有效。在那种特殊情况下,map&lt;&gt;::operator[]更安全的,因为它保证程序没有未定义的行为。
    • @DavidRodríguez-dribeas,这是错误。由于代码中没有if 签入,并不意味着不需要/不打算这样做。代码示例过于本地化。在现实世界中,一个理智的编码员将有一个find() 后跟一个if 条件。编写脏代码来保存未定义的行为不是解决方案。
    • @iammilind:我想问题在于 safe 的定义。我的观点是语义不同,您可以声称find 不会修改容器,但这并不会使find 操作更安全。而在相反的一端:使用operator[],您可以保证获得引用,因此使用它是安全(是的,它会修改容器,不,您不会导致未定义的行为) ,而使用find,用户代码需要检查返回值,因为自动取消引用它是不安全的。对我来说更容易出错意味着不太安全
    【解决方案3】:

    map 中的 [] 运算符不是常数,它是对数。大多数书籍都强调这一事实,并指出这有点误导。所以 find 和 [] 运算符都具有相同的复杂性。

    请注意,即使条目不存在,[] 运算符也会创建条目,而在这种情况下 find 将返回 end()。

    【讨论】:

      【解决方案4】:

      此代码和文档选自cplusplus.com

      // accessing mapped values
      #include <iostream>
      #include <map>
      #include <string>
      using namespace std;
      
      int main ()
      {
        map<char,string> mymap;
      
        mymap['a']="an element";
        mymap['b']="another element";
        mymap['c']=mymap['b'];
      
        cout << "mymap['a'] is " << mymap['a'] << endl;
        cout << "mymap['b'] is " << mymap['b'] << endl;
        cout << "mymap['c'] is " << mymap['c'] << endl;
        cout << "mymap['d'] is " << mymap['d'] << endl;
      
        cout << "mymap now contains " << (int) mymap.size() << " elements." << endl;
      
        return 0;
      }
      
      OP:
      mymap['a'] is an element
      mymap['b'] is another element
      mymap['c'] is another element
      mymap['d'] is
      mymap now contains 4 elements.
      

      注意最后一次访问(对元素 'd')如何使用该键在映射中插入一个新元素并初始化为其默认值(一个空字符串),即使访问它只是为了检索其值。成员函数 map::find 不会产生这种效果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-03
        • 2017-06-29
        • 1970-01-01
        相关资源
        最近更新 更多