Почему делает станд.:: оператор карты [] создает объект, если ключ не существует?

Похож на OpenGL, пытается сообщить о некоторой ошибке относительно Win2003, однако Вы не настроили свою систему, где произвести регистрирующуюся информацию

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

import logging
logging.basicConfig()

документация Контроля относительно вход модуль для получения большего количества информации о конфигурации концептуально это подобно log4J.

34
задан Ates Goral 5 May 2010 в 16:26
поделиться

9 ответов

To answer your real question: there's no convincing explanation as to why it was done that way. "Just because".

Since std::map is an associative container, there's no clear pre-defined range of keys that must exist (or not exist) in the map (as opposed to the completely different situation with std::vector). That means that with std::map, you need both non-insering and inserting lookup functionality. One could overload [] in non-inserting way and provide a function for insertion. Or one could do the other way around: overload [] as an inserting operator and provide a function for non-inserting search. So, someone sometime decided to follow the latter approach. That's all there's to it.

If they did it the other way around, maybe today someone would be asking here the reverse version of your question.

7
ответ дан 27 November 2019 в 16:53
поделиться

Он предназначен для целей назначения:


void test()
{
   std::map<std::string, int >myMap;
   myMap["hello"] = 5;
}
4
ответ дан 27 November 2019 в 16:53
поделиться

Поскольку operator [] возвращает ссылку на само значение, и поэтому единственный способ указать на проблему - вызвать исключение (и в целом STL редко выдает исключения).

Если вам не нравится такое поведение, вы можете использовать вместо него map :: find . Он возвращает итератор вместо значения. Это позволяет ему возвращать специальный итератор, когда значение не найдено (он возвращает map :: end ), но также требует, чтобы вы разыменовали итератор, чтобы получить значение.

22
ответ дан 27 November 2019 в 16:53
поделиться

Стандарт говорит (23.3.1.2/1), что operator [] возвращает (* ((insert (make_pair (x, T ()))). First)). Second . Вот в чем причина. Он возвращает ссылку T & . Невозможно вернуть недействительную ссылку. И он возвращает ссылку, потому что, я думаю, это очень удобно, не так ли?

13
ответ дан 27 November 2019 в 16:53
поделиться

Я думаю, это в основном потому, что в случае карты (в отличие от вектора, например) это довольно дешево и легко сделать - вам нужно создать только один элемент. В случае вектора они могут расширить вектор, чтобы сделать новый индекс действительным, но если ваш новый индекс намного превышает то, что уже есть, добавление всех элементов до этого момента может быть довольно дорогостоящим. Когда вы расширяете вектор, вы также обычно указываете значения новых элементов, которые нужно добавить (хотя часто со значением по умолчанию). В этом случае не было бы способа указать значения элементов в пространстве между существующими элементами и новым.

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

4
ответ дан 27 November 2019 в 16:53
поделиться

Ответ будет потому, что им нужна была и удобная, и быстрая реализация.

Базовая реализация вектора - это массив. Итак, если в массиве 10 записей, а вам нужна запись 5, функция T & vector :: operator [] (5) просто возвращает headptr + 5. Если вы запрашиваете запись 5400, она возвращает headptr + 5400.

Базовая реализация карты обычно представляет собой дерево. Каждый узел выделяется динамически, в отличие от вектора, который согласно стандарту должен быть непрерывным. Итак, nodeptr + 5 ничего не означает, а map ["некоторая строка"] не означает rootptr + offset ("некоторая строка").

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

1
ответ дан 27 November 2019 в 16:53
поделиться

Это позволяет вставлять новые элементы с оператором [] , например:

std::map<std::string, int> m;
m["five"] = 5;

5 присваивается значению, возвращаемому m ["пять"] , которое является ссылка на вновь созданный элемент. Если оператор [] не будет вставлять новые элементы, это не может работать таким образом.

3
ответ дан 27 November 2019 в 16:53
поделиться

Разница в том, что карта хранит «индекс», то есть значение, хранящееся в карте (в его базовое дерево RB) является std :: pair , а не просто «индексированным» значением. Всегда есть map :: find () , который сообщит вам, существует ли пара с данным ключом.

1
ответ дан 27 November 2019 в 16:53
поделиться

map.insert (ключ, элемент); проверяет наличие ключа на карте, но не перезаписывает существующее значение.

map.operator [key] = item; проверяет, находится ли ключ на карте, и перезаписывает любое существующее значение элементом.

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

3
ответ дан 27 November 2019 в 16:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: