I have some (C++14) code that looks like this:
map<int, set<string>> junk;
for (int id : GenerateIds()) {
try {
set<string> stuff = GetStuff();
junk[id] = stuff;
} catch (const StuffException& e) {
...
}
}
This works. Sometimes GetStuff()
throws an exception, which works fine, because if it does, I don't want a value in the junk map then.
But at first I'd written this in the loop, which doesn't work:
junk[id] = GetStuff();
More precisely, even when GetStuff()
throws an exception, junk[id]
is created (and assigned an empty set).
This isn't what I'd expect: I'd expect them to function the same way.
Is there a principle of C++ that I've misunderstood here?
Before C++17 there was no sequencing between the left- and right-hand side of assignment operators.
It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).
That means the evaluation order is unspecified , which means it's up to the implementation to perform the evaluation in the order in which it wants, and in this case it evaluates the left-hand side first.
See this evaluation order reference for more details (especially point 20).
std::map::operator[]
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
junk[id]
causes the above mentioned insertion and after that has already happened GetStuff()
throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff();
may not do the insertion if GetStuff()
throws.
You're misunderstanding how operator[]
works on std::map
.
It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator=
to set a new value.
To make this work the way you expect, you'll need to use std::map::insert
(*):
junk.insert(std::make_pair(id, GetStuff()));
Caveat : insert
will only add the value if id
is not already mapped.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.