Подтвердить что ты не робот

Рекомендуемый способ вставки элементов в карту

Возможный дубликат:
В STL-картах лучше использовать map:: insert, чем []?

Мне было интересно, когда я вставляю элемент в карту, каков рекомендуемый способ. Должен ли я

map[key] = value;

или

map.insert(std::pair<key_type, value_type>(key, value));

Я сделал следующий быстрый тест:

#include <map>
#include <string>
#include <iostream>

class Food {
public:
    Food(const std::string& name) : name(name) { std::cout << "constructor with string parameter" << std::endl; }
    Food(const Food& f) : name(f.name) { std::cout << "copy" << std::endl; }
    Food& operator=(const Food& f) { name = f.name; std::cout << "=" << std::endl; return *this; } 
    Food() { std::cout << "default" << std::endl; }
    std::string name;
};

int main() {
    std::map<std::string, Food> m0;

/*
1) constructor with string parameter
2) copy
3) copy
4) copy
*/
    m0.insert(std::pair<std::string, Food>("Key", Food("Ice Cream")));

/*
1) constructor with string parameter
2) default
3) copy
4) copy
5) =
*/
    // If we do not provide default constructor.
    // C2512: 'Food::Food' : no appropriate default constructor available
    m0["Key"] = Food("Ice Cream");
}
  • Я понимаю, используя функцию-член insert, будет задействован вызов меньшей функции. Таким образом, используется insert рекомендуемый способ?
  • Почему нужен конструктор по умолчанию, когда используется способ map[key] = value?

Я знаю, что insert не перезаписывает пару значений существования, но map[key] = value делает. Однако, это единственный фактор, который я принимаю во внимание, когда пытаюсь выбрать из обоих?

Как насчет

  • Производительность
  • Доступность конструктора значений по умолчанию
  • ???
4b9b3361

Ответ 1

  • insert не рекомендуется - это один из способов вставить в карту. Разница с operator[] заключается в том, что insert может определить, вставлен ли элемент в карту. Кроме того, если ваш класс не имеет конструктора по умолчанию, вы вынуждены использовать insert.
  • operator[] нужен конструктор по умолчанию, потому что карта проверяет, существует ли элемент. Если это не так, он создает один, используя конструктор по умолчанию, и возвращает ссылку (или константную ссылку на нее).

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

Ответ 2

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

if ( !myMap.insert( std::make_pair( key, value ) ).second ) {
    //  Element already present...
}

Используйте [], если вы хотите перезаписать возможно существующий элемент:

myMap[ key ] = value;
assert( myMap.find( key )->second == value ); // post-condition

Эта форма перезапишет любую существующую запись.

Ответ 3

Цитата:

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

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

EDIT:

Это напоминает мне еще один недавний вопрос: зачем использовать at() вместо оператора [] для извлечения значений из вектора. По-видимому, в() выбрасывается исключение, если индекс выходит за пределы, тогда как [] - нет. В этих ситуациях всегда лучше искать документацию о функциях, поскольку они дадут вам все подробности. Но в общем случае нет (или, по крайней мере, не должно быть) двух функций/операторов, которые делают то же самое.

Я предполагаю, что внутри, insert() сначала проверит для записи, а потом сам будет использовать оператор [].

Ответ 4

map[key] = value предоставляется для упрощения синтаксиса. Легче читать и писать.

Причиной, по которой вам нужен конструктор по умолчанию, является то, что map[key] оценивается перед назначением. Если на карте нет ключа, новый создается (со стандартным конструктором), а ссылка на него возвращается из operator[].