Assignment in C++ occurs despite exception in right side

1145 views c++

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?

answered question

Also see [c++ map exception safe insert]() and [Making operations on standard-library containers strongly exception safe]()

3 Answers



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 this and then GetStuff() throws.

posted this

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.

posted this

Before C++17 there was no sequencing between the left- and right-hand side of overloaded 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 implementation-defined, which means your compiler performs the evaluation of the left-hand side first.

See this evaluation order reference for more details (especially point 20).

posted this

Have an answer?


Please login first before posting an answer.