Ответ на этот вопрос также зависит от того, насколько дорого создать тип значения, который вы храните на карте:
typedef std::map <int, int> MapOfInts;
typedef std::pair <MapOfInts::iterator, bool> IResult;
void foo (MapOfInts & m, int k, int v) {
IResult ir = m.insert (std::make_pair (k, v));
if (ir.second) {
// insertion took place (ie. new entry)
}
else if ( replaceEntry ( ir.first->first ) ) {
ir.second->second = v;
}
}
Для типа значения, такого как int, вышеупомянутое будет более эффективным, чем поиск, за которым следует вставка (при отсутствии оптимизации компилятора). Как указано выше, это связано с тем, что поиск по карте происходит только один раз.
Однако, вызов для вставки требует, чтобы у вас уже было создано новое «значение»:
class LargeDataType { /* ... */ };
typedef std::map <int, LargeDataType> MapOfLargeDataType;
typedef std::pair <MapOfLargeDataType::iterator, bool> IResult;
void foo (MapOfLargeDataType & m, int k) {
// This call is more expensive than a find through the map:
LargeDataType const & v = VeryExpensiveCall ( /* ... */ );
IResult ir = m.insert (std::make_pair (k, v));
if (ir.second) {
// insertion took place (ie. new entry)
}
else if ( replaceEntry ( ir.first->first ) ) {
ir.second->second = v;
}
}
Чтобы вызвать 'insert', мы платим за дорогой вызов для создания нашего типа значения - и из того, что вы сказали в вопросе, вы не будете использовать это новое значение в 20% случаев. В приведенном выше случае, если изменение типа значения карты не является вариантом, более эффективно сначала выполнить 'find', чтобы проверить, нужно ли нам создать элемент.
В качестве альтернативы тип значения карты можно изменить, чтобы сохранить дескрипторы данных, используя ваш любимый тип интеллектуального указателя. При вызове insert используется нулевой указатель (очень дешевый в построении), и только при необходимости создается новый тип данных.