edit:这个问题本不应该结束,如果你看看答案,你会发现它们完全不同(旧问题没有提到C++17(。
我读了一篇PVS博客文章,他们提到了以下错误。
(减少(
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
根据博客文章,这是错误的。我一直认为映射的运算符[]调用是一个函数调用,所以.size((在[]之前排序,因为函数充当序列点。
为什么这是一个bug?
注意:我知道从C++11开始就不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
C++17之前
§1.9程序执行[简介执行](n3690 c++14草案(
- 除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值为未排序
和5.17[expr.ass]没有提到内置赋值的操作数之间的任何排序。因此,内建赋值运算符=
的两个操作数的求值是相对于彼此不排序的。
CCD_ 2和CCD_。
考虑:
-
m[val]
具有修改贴图大小(标量(的副作用 -
m.size()
的值计算访问地图的大小
§1.9程序执行[简介执行](n3690 c++14草案(
- […]如果标量对象上的副作用相对于[…]或使用相同值的值计算未排序标量对象,行为未定义
所以是的,行为确实是未定义的。
C++17
§8.5.18赋值和复合赋值运算符[expr.ass](n4713C++17草案(
- 赋值运算符(=([…]右操作数在左操作数之前排序
因此定义了行为。m.size()
将在m[val]
之前进行评估