Odpowiedź na to pytanie zależy również od tego, jak kosztowne jest utworzenie typu wartości, który przechowujesz na mapie:
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) {
}
else if ( replaceEntry ( ir.first->first ) ) {
ir.first->second = v;
}
}
W przypadku typu wartości, takiego jak int, powyższe będzie bardziej wydajne niż wyszukiwanie, po którym następuje wstawienie (w przypadku braku optymalizacji kompilatora). Jak wspomniano powyżej, dzieje się tak, ponieważ przeszukiwanie mapy odbywa się tylko raz.
Jednak wywołanie wstawiania wymaga, aby masz już skonstruowaną nową „wartość”:
class LargeDataType { };
typedef std::map <int, LargeDataType> MapOfLargeDataType;
typedef std::pair <MapOfLargeDataType::iterator, bool> IResult;
void foo (MapOfLargeDataType & m, int k) {
LargeDataType const & v = VeryExpensiveCall ( );
IResult ir = m.insert (std::make_pair (k, v));
if (ir.second) {
}
else if ( replaceEntry ( ir.first->first ) ) {
ir.first->second = v;
}
}
Aby wywołać „wstaw”, płacimy za drogie wywołanie w celu skonstruowania naszego typu wartości - iz tego, co powiedziałeś w pytaniu, nie będziesz używać tej nowej wartości w 20% przypadków. W powyższym przypadku, jeśli zmiana typu wartości mapy nie jest opcją, bardziej efektywne jest wykonanie najpierw polecenia „znajdź”, aby sprawdzić, czy musimy skonstruować element.
Alternatywnie, typ wartości mapy można zmienić, aby przechowywać uchwyty do danych przy użyciu ulubionego typu inteligentnego wskaźnika. Wywołanie wstawiania używa pustego wskaźnika (bardzo tanie w budowie) i tylko w razie potrzeby konstruowany jest nowy typ danych.