Обычно, если вы делаете поиск и, возможно, вставку, то вы хотите сохранить (и получить) старое значение, если оно уже существовало. Если вы просто хотите перезаписать любое старое значение, map[foo_obj]="some value"
сделает это.
Вот как вы можете получить старое значение или вставить новое, если оно не существует, с одним поиском карты:
typedef std::map<Foo*,std::string> M;
typedef M::iterator I;
std::pair<I,bool> const& r=my_map.insert(M::value_type(foo_obj,"some value"));
if (r.second) {
// value was inserted; now my_map[foo_obj]="some value"
} else {
// value wasn't inserted because my_map[foo_obj] already existed.
// note: the old value is available through r.first->second
// and may not be "some value"
}
// in any case, r.first->second holds the current value of my_map[foo_obj]
Это достаточно распространенная идиома, которую вы можете использовать вспомогательную функцию:
template <class M,class Key>
typename M::mapped_type &
get_else_update(M &m,Key const& k,typename M::mapped_type const& v) {
return m.insert(typename M::value_type(k,v)).first->second;
}
get_else_update(my_map,foo_obj,"some value");
Если у вас есть дорогостоящее вычисление для v, которое вы хотите пропустить, если оно уже существует (например, памятка), вы также можете обобщить это:
template <class M,class Key,class F>
typename M::mapped_type &
get_else_compute(M &m,Key const& k,F f) {
typedef typename M::mapped_type V;
std::pair<typename M::iterator,bool> r=m.insert(typename M::value_type(k,V()));
V &v=r.first->second;
if (r.second)
f(v);
return v;
}
, например,
struct F {
void operator()(std::string &val) const
{ val=std::string("some value")+" that is expensive to compute"; }
};
get_else_compute(my_map,foo_obj,F());
Если сопоставленный тип не является конструируемым по умолчанию, тогда заставьте F предоставить значение по умолчанию или добавьте другой аргумент в get_else_compute.