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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With