Die Antwort auf diese Frage hängt auch davon ab, wie teuer es ist, den Werttyp zu erstellen, den Sie in der Karte speichern:
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;
}
}
Für einen Werttyp wie ein int ist das Obige effizienter als ein Fund, gefolgt von einer Einfügung (ohne Compiler-Optimierungen). Wie oben erwähnt, liegt dies daran, dass die Suche in der Karte nur einmal erfolgt.
Für den Aufruf zum Einfügen muss jedoch der neue "Wert" bereits erstellt sein:
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;
}
}
Um 'Einfügen' aufzurufen, zahlen wir für den teuren Aufruf zur Erstellung unseres Werttyps - und nach dem, was Sie in der Frage gesagt haben, werden Sie diesen neuen Wert in 20% der Fälle nicht verwenden. Wenn im obigen Fall das Ändern des Kartenwerttyps keine Option ist, ist es effizienter, zuerst die Suche durchzuführen, um zu überprüfen, ob das Element erstellt werden muss.
Alternativ kann der Wertetyp der Karte geändert werden, um Handles für die Daten unter Verwendung Ihres bevorzugten Smart-Pointer-Typs zu speichern. Der Aufruf zum Einfügen verwendet einen Nullzeiger (sehr billig zu erstellen) und nur bei Bedarf wird der neue Datentyp erstellt.