I have an std::unordered_map, and I want both to increment the first value in a std::pair, hashed by key, and to create a reference to key. For example:
std::unordered_map<int, std::pair<int, int> > hash;
hash[key].first++;
auto it(hash.find(key));
int& my_ref(it->first);
I could, instead of using the [] operator, insert the data with insert(), but I’d allocate a pair, even if it were to be deallocated later, as hash may already have key — not sure of it, though. Making it clearer:
// If "key" is already inserted, the pair(s) will be allocated
// and then deallocated, right?
auto it(hash.insert(std::make_pair(key, std::make_pair(0, 0))));
it->second.first++;
// Here I can have my reference, with extra memory operations,
// but without an extra search in `hash`
int& my_ref(it->first);
I’m pretty much inclined to use the first option, but I can’t seem to decide which one is the best. Any better solution to this?
P.S.: an ideal solution for me would be something like an insertion that does not require an initial, possibly useless, allocation of the value.
As others have pointed out, a “allocating” a
std::pair<int,int>is really nothing more than copying two integers (on the stack). For themap<int,pair<int,int>>::value_type, which ispair<int const, pair<int, int>>you are at threeints, so there is no significant overhead in using your second approach. You can slightly optimize by usingemplaceinstead ofinserti.e.:Your first approach, using both
hash[key]andhash.find(key)is bound to be more expensive, because an element search will certainly be more expensive than an iterator dereference.Premature copying of arguments on their way to construction of the
unordered_map<...>::value_typeis a negligible problem, when all arguments are justints. But if instead you have a heavyweightkey_typeor apairof heavyweight types asmapped_type, you can use the following variant of the above to forward everything by reference as far as possible (and use move semantics for rvalues):