STL MAP должен использовать идентификатор find () или [n] для поиска элемента на карте?

Я запутался, что эффективнее?

Поскольку мы можем напрямую обращаться к карте, зачем нам использовать 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;
}

заранее спасибо! :)


person mister    schedule 14.05.2012    source источник


Ответы (4)


Использование find означает, что вы случайно не создаете новый элемент на карте, если ключ не существует, и, что более важно, это означает, что вы можете использовать find для поиска элемента если все, что у вас есть, это постоянная ссылка на карту.

Это, конечно, означает, что вы должны проверить возвращаемое значение 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); }
}
person Kerrek SB    schedule 14.05.2012
comment
+1 Это абсолютно важно, когда вы не хотите создавать элемент, если он не найден. - person Ganesh M; 14.05.2012

Поскольку мы можем напрямую обращаться к карте, зачем нам использовать find?

Потому что map<>::operator[] иногда бывает неприятным. Если элемент не существует, то:

  • он вставляет это
  • значение инициализировать его
  • возвращает ссылку на значение

Таким образом, он всегда возвращает действительную ссылку на значение, даже если ключ ранее не существовал. Такое поведение не предназначено много раз.

С другой стороны, map<>::find() безопаснее; потому что он возвращает end(), если значение не выходит. Другое преимущество find() заключается в том, что он возвращает итератор, который содержит ссылки как на ключ (first), так и на значение (second).

person iammilind    schedule 14.05.2012
comment
operator[] возвращает ссылку на значение, а не ключ. - person jpalecek; 14.05.2012
comment
@jpalecek, да, его поменяли. Спасибо - person iammilind; 14.05.2012
comment
map<>::find() безопаснее. Ну, на самом деле нет. Самый простой пример — код в вопросе, где пользователь не проверяет, действителен ли итератор. В этом конкретном случае map<>::operator[] безопаснее, так как гарантирует отсутствие неопределенного поведения программы. - person David Rodríguez - dribeas; 14.05.2012
comment
@DavidRodríguez-dribeas, это неправильно. Поскольку в коде нет проверки if, это не значит, что она не нужна/не предназначена. Пример кода слишком локализован. В реальном мире у здравомыслящего кодера будет условие find(), за которым следует условие if. Написание грязного кода для сохранения неопределенного поведения не является решением. - person iammilind; 14.05.2012
comment
@iammilind: я думаю, проблема в определении safe. Я хочу сказать, что семантика другая, и вы можете утверждать, что find не изменит контейнер, но это не сделает операцию find более безопасной. Скорее на противоположном конце: с operator[] вы гарантированно получите ссылку, поэтому ее безопасно использовать (да, она изменяет контейнер, нет, вы не вызываете неопределенное поведение), в то время как с find пользовательский код должен проверять возвращаемое значение, так как безопасно автоматически разыменовывать его. Для меня более подверженный ошибкам означает менее безопасный. - person David Rodríguez - dribeas; 14.05.2012

Оператор [] в карте не является константой, он логарифмический. Большинство книг подчеркивают этот факт и указывают, что он немного вводит в заблуждение. Таким образом, оператор find и оператор [] имеют одинаковую сложность.

Обратите внимание, что оператор [] создаст запись, даже если она не существует, в то время как find в этом случае вернет end().

person Ivaylo Strandjev    schedule 14.05.2012

Этот код и документ взяты с сайта 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 не дает такого эффекта.

person tuxuday    schedule 14.05.2012