尽管右边有异常,C + + 中的赋值仍然会发生

我有一些(C + + 14)代码如下:

map<int, set<string>> junk;
for (int id : GenerateIds()) {
try {
set<string> stuff = GetStuff();
junk[id] = stuff;
} catch (const StuffException& e) {
...
}
}

这个管用。有时 GetStuff()会抛出一个异常,这个异常工作得很好,因为如果它抛出了异常,那么我就不希望垃圾映射中出现一个值。

但是一开始我在循环中写了这个,这个不起作用:

junk[id] = GetStuff();

更准确地说,即使 GetStuff()抛出异常,也会创建 junk[id](并分配一个空集)。

这不是我所期望的: 我期望它们以同样的方式运作。

这里有没有我误解的 C + + 原则?

4437 次浏览

Map: : Operator []

对映射到等效于 如果该键不存在,则执行插入操作。

junk[id]引起上面提到的插入,之后已经发生了 GetStuff()抛出。注意,在 C + + 14中,这些事情发生的顺序是实现定义的,所以如果使用不同的编译器,当 GetStuff()抛出。

你误解了 operator[]std::map上是如何工作的。

它返回对映射项的引用。因此,代码首先在该位置插入一个默认项,然后调用 operator=来设置一个新值。

为了使这个工作按照您预期的方式进行,您需要使用 std::map::insert(*) :

junk.insert(std::make_pair(id, GetStuff()));

警告 : 如果 id尚未映射,insert将只添加值。

在 C + + 17之前,赋值运算符的左边和右边之间没有顺序。

在 C + + 17中,第一次引入了显式排序(首先计算右侧)。

这意味着求值顺序是 没有具体说明,这意味着由实现按照它希望的顺序执行求值,在这种情况下,它首先求值左边。

有关详细信息,请参阅 这个评估指令参考(特别是第20点)。