NoS*_*tAl 4 c++ sequence-points unspecified-behavior
编辑:这个问题不应该被关闭,如果你查看答案,你会发现它们完全不同(旧问题没有提到 C++17)。
我正在阅读一篇 PVS博客文章,他们提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
Run Code Online (Sandbox Code Playgroud)
根据博客文章,这是错误的。我一直认为 operator [] 对 map 的调用是一个函数调用,所以 .size() 在 [] 之前被排序,因为函数充当序列点。
那么为什么这是一个错误呢?
注意:我知道从 C++11 开始就不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
§ 1.9 程序执行 [intro.execution](n3690 c++14 草案)
- 除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的计算是无序的。
和 5.17 [expr.ass] 没有提到内置赋值操作数之间的任何排序。因此,对内置赋值运算符的两个操作数的计算=彼此之间是无序的。
m[val]并且m.size()可以以任何顺序进行评估(甚至可以重叠 - 交错 CPU 指令)。
考虑:
m[val] 具有修改地图大小(标量)的副作用
m.size()访问地图大小的值计算
§ 1.9 程序执行 [intro.execution](n3690 c++14 草案)
- [...] 如果对标量对象的副作用相对于 [...] 或使用相同标量对象的值的值计算是未排序的,则行为未定义。
所以是的,行为确实是未定义的。
§8.5.18 赋值和复合赋值运算符 [expr.ass](n4713 C++17 草案)
- 赋值运算符 (=) [...] 右操作数排在左操作数之前。
所以行为被定义了。m.size()之前会被评估m[val]
| 归档时间: |
|
| 查看次数: |
103 次 |
| 最近记录: |