Избегайте двойного поиска или ненужной конструкции с помощью std :: unordered_map (и других) - PullRequest
4 голосов
/ 29 мая 2019

Я хотел бы найти элемент с ключом на std::unordered_map или вставить его, если он еще не существует.

С cppreference.com :

станд :: unordered_map :: * 1009 устанавливать *

Вставляет новый элемент в контейнер, созданный на месте с заданными аргументами, если в контейнере нет элемента с ключом.

...

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

...

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

Я протестировал его для своих сред, и он фактически создает элемент, даже если тот же ключ уже существует.

Это может быть серьезной проблемой производительности.

Из c ++ 17 есть try_emplace, который избегает этой конструкции, если вставка не происходит.

Я ограничен c ++ 14 и после осмотра нахожу две альтернативы для того же поведения:

  • сначала используйте std::unordered_map::find, а если элемент не существует, тогда используйте std::unordered_map::emplace. Если ключ не существует , я плачу за избыточный поиск контейнера .

  • используйте std::unordered_map::emplace. Если ключ существует , я плачу за ненужный объект строительства и разрушения .

Правильно ли мое предположение, что я должен принять решение по этому компромиссу до C ++ 17?

1 Ответ

2 голосов
/ 29 мая 2019

Правильно ли мое предположение, что я должен принять решение по этому компромиссу до C ++ 17?

Да.

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

...