c++ - 是否将地图大小作为值插入地图未定义的行为?
问题描述
编辑:这个问题不应该被关闭,如果你看看答案,你会发现它们完全不同(旧问题没有提到 C++17)。
我正在阅读一篇 PVS博客文章,其中提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
根据博客文章,这是错误的。我一直认为 map 的 operator [] 调用是一个函数调用,因此 .size() 在 [] 之前排序,因为函数充当序列点。
那么为什么这是一个错误呢?
注意:我知道自 C++11 以来不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
解决方案
预 C++17
§ 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 草案)
- [...] 如果标量对象的副作用相对于 [...] 或使用相同标量对象的值的值计算是无序的,则行为未定义。
所以是的,行为确实是未定义的。
C++17
§8.5.18 赋值和复合赋值运算符 [expr.ass](n4713 C++17 草案)
- 赋值运算符 (=) [...] 右操作数在左操作数之前排序。
所以定义了行为。m.size()
将在之前进行评估m[val]
推荐阅读
- apache-nifi - 如何在 ETL 管道中的某处插入识别敏感信息的过程?
- reactjs - React-Router DOM 不渲染其他页面的内容
- python - 如何在第 1414 个元素后解决 pandas 数据帧上的此关键错误
- sql - 如何用英文数字搜索postgres但返回波斯语/阿拉伯语?
- python - Python 的 random.shuffle() 如何在不返回任何内容的情况下更改列表的值,这是任何 Python 编码器都可以做的事情吗?
- c# - LINQ .All() - 总是返回 true
- python - 如何在 spaCy 中分析较大的文本?
- html - CSS WOW Animation.css 库与 transform css 属性一起使用时会导致定位后跳转
- r - BERT 未在控制台中显示 R shell
- python - 如果它不在最后一行,Python 无法打开写在文本文档上的文件路径