В чем разница между использованием функции вставки при использовании std :: map.insert ("xyz") или просто map [ind] = "xyz" - PullRequest
4 голосов
/ 08 февраля 2011

В следующем примере каковы плюсы и минусы использования 1) против 2).Есть ли какие-то преимущества в распределении памяти, какие-то преимущества, если не хватает места?

map <  int, string> Employees;  



  // 1) Assignment using array index notation  

   Employees[5234] = "Mike C.";  

  // 2) Assignment using member function insert() and STL pair  

    Employees.insert(std::pair<int, * char>(1923,"David D."));  

Ответы [ 5 ]

5 голосов
/ 08 февраля 2011

Первый создает сопоставление с ключом 5234 и возвращает ссылку на содержащуюся в нем строку, которой назначается «Майк С» - важно отметить, что если ключ уже существует, он будет перезаписывать значение в этом ключе (потому что возвращается ссылка на значение).

Второй подход проверяет наличие ключа и не перезаписывает его, если он уже существует.

Что касается выделения памяти, то оба увеличат размер карты на 1, если отображение не существует. Вышесказанное является единственной разницей между двумя подходами AFAIK.

4 голосов
/ 08 февраля 2011
  • Если key действительно не на карте, то Employees[key] = value добавляет новую пару ключ-значение на карту.

  • Если key уже существует, то Employees[key] = value просто обновляет значение с данным ключом.

  • Employees.insert() всегда добавляет новую пару ключ-значение на карту. Однако, если ключ уже существует, он ничего не делает. Если вы хотите, чтобы разные элементы имели один и тот же ключ, вы можете использовать multimap .

4 голосов
/ 08 февраля 2011

Разница здесь в том, что вариант 1 назначит значение ключу во всех случаях, когда вариант два может вернуть std :: pair, содержащий итератор элемента, плюс логическое уведомление об успешной вставке. Это означает, что если элемент 1923 уже существует на вашей карте, функция вставки вернет <iterator, false>, уведомив вас о том, что ключ уже существует на карте и не будет перезаписывать его.

std::map<int, char*> aMap;
aMap[12] = "An Entry";

std::pair< std::map<int, char*>::iterator, bool > result;
result = aMap.insert(12, "A new entry");

//now result.first points to the existing entry at 12, result.second == false

Единственное преимущество производительности, о котором я могу подумать, это то, что вы экономите время обработки, не выполняя if(aMap.count(12) == 0) или if(aMap.find(12) == aMap.end()) перед выполнением операции вставки.

1 голос
/ 08 февраля 2011

Очень полезно знать эту разницу между insert и operator[]

Вы можете реально реализовать operator[] в терминах insert, так как он возвращает pair<iterator,bool>

Таким образомможно (и возможно, возможно) реализовать:

Value& map<K,T>::operator[]( const Key& key )
{
   return insert( make_pair(key, Value()) ).first->second;
}

Практическое применение в использовании: в типичной ситуации с кэш-памятью с "ленивой загрузкой" у вас может быть map<Key, shared_ptr<Value> >

Обычно программист запускаетсяс find следующим образом:

  const_iterator iter = theMap.find(key);
  if( iter!= theMap.end())
     return iter->second;
  else
  {
    // create the item then insert it
  }

Лучший подход:

shared_ptr<Value> value = theMap[key];
if( !value )
{
   value.reset( /*load logic */ )
}
return value;

В многопоточной ситуации, описанной выше, вместо shared_ptr использовать класс-оболочку, который реализует "boost ::однажды "логика"Допустим, загрузка объекта занимает много времени.В классическом случае вы, вероятно, заблокируете всю карту, пока будете искать элемент и затем создавать его.Так что никакой другой поток не может использовать карту вообще.

Вместо этого мы теперь блокируем карту только для поиска и создаем объект в его состоянии "ONCE_INIT".Затем мы разблокируем карту и используем boost::call_once для инициализации фактического элемента.Обратите внимание, что в течение этого времени возможно, что элемент был создан другим потоком, а не тем, который добавил его на карту, но это не имеет особого значения: он будет создан ровно один раз, и в этом нет конфликта потоков.(Это реализация блокировки на уровне записей).Обратите внимание, что если бы мы использовали первую конструкцию (find, insert), мы бы не смогли этого сделать.

1 голос
/ 08 февраля 2011

Подробно вы можете прочитать в книге Скотта Мейерса «Эффективный STL» (тема 24).

...