Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it faster to use iterator-based search-and-use in STL associative containers?

Tags:

c++

c++17

c++20

Let's say I'm trying to check if an item exists in an associative container, and do something to it if it does. The simple way to do this is as follows:

std::unordered_map<std::string, Whatever> thisIsAMap;

// C++17
if (thisIsAMap.count("key") > 0u) { doThing(thisIsAMap["key"]); }
// C++20
if (thisIsAMap.contains("key")) { doThing(thisIsAMap["key"]); }

However, this has always seemed somewhat wasteful to me, as it involves finding the same item twice, which might be quite an expensive operation. Instead, I tend to do this:

auto found = thisIsAMap.find("key");
if (found != thisIsAMap.end()) { doThing(found->second); }

This only requires finding the item once, and then using it.

Is the latter approach actually any better? Are there any good reasons to use either approach over the other?

like image 789
Stefan Bauer Avatar asked Oct 17 '20 17:10

Stefan Bauer


1 Answers

Is the latter approach actually any better?

Yes. For several reasons.

First, doing one map lookup is definitely at least as fast as doing two map lookups. Best case, the compiler optimizes out the second lookup, but I've never actually seen that happen in practice and that seems like a lot to rely on.

Second, using find means you only have to type "key" once, rather than twice, which just reduces a potential source of error.

Third, using [] requires the value type to be default constructible - so in addition to being worse for performance and software engineering reasons, it also can add more requirements to your type that you may not be able to meet.

Fourth, it's just more obvious from a code-reading perspective that you're looking up an item and then using that item if it's found... rather than looking up an item and happening to look up the same item again.

like image 173
Barry Avatar answered Sep 28 '22 06:09

Barry