将地图大小作为值插入到地图未定义行为中吗?
Is inserting map size as value into a map undefined behavior?
编辑:这个问题应该没有关闭,如果你看一下答案你会发现它们是完全不同的(旧问题没有提到C++17) .
我正在阅读 PVS blog post,其中提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
根据博客 post,这是错误的。
我一直认为 operator [] 对 map 的调用是一个函数调用,所以 .size() 在 [] 之前排序,因为函数充当序列点。
那么为什么这是一个错误?
注意:我知道自 C++11 以来不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
C++17 之前
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
- Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are
unsequenced.
和 5.17 [expr.ass] 没有提到内置赋值操作数之间的任何顺序。因此,内置赋值运算符 =
的两个操作数的求值相互之间是无序的。
m[val]
和 m.size()
可以按任何顺序计算(甚至可以重叠 - 交错 CPU 指令)。
正在考虑:
m[val]
具有修改地图大小(标量)的副作用
m.size()
的值计算访问地图的大小
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
- [...] If a side effect on a scalar object is unsequenced relative to either [...] or a value computation using the value of the same
scalar object, the behavior is undefined.
所以是的,行为确实是未定义的。
C++17
§8.5.18 Assignment and compound assignment operators [expr.ass] (n4713
C++17 draft)
- The assignment operator (=) [...] The right operand is sequenced before the left operand.
因此行为已定义。 m.size()
将在 m[val]
之前计算
编辑:这个问题应该没有关闭,如果你看一下答案你会发现它们是完全不同的(旧问题没有提到C++17) .
我正在阅读 PVS blog post,其中提到了以下错误。
(减少)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
根据博客 post,这是错误的。 我一直认为 operator [] 对 map 的调用是一个函数调用,所以 .size() 在 [] 之前排序,因为函数充当序列点。
那么为什么这是一个错误?
注意:我知道自 C++11 以来不存在序列点,但我使用它们是因为新的措辞对我来说更难理解。
C++17 之前
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
- Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
和 5.17 [expr.ass] 没有提到内置赋值操作数之间的任何顺序。因此,内置赋值运算符 =
的两个操作数的求值相互之间是无序的。
m[val]
和 m.size()
可以按任何顺序计算(甚至可以重叠 - 交错 CPU 指令)。
正在考虑:
m[val]
具有修改地图大小(标量)的副作用m.size()
的值计算访问地图的大小
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
- [...] If a side effect on a scalar object is unsequenced relative to either [...] or a value computation using the value of the same scalar object, the behavior is undefined.
所以是的,行为确实是未定义的。
C++17
§8.5.18 Assignment and compound assignment operators [expr.ass] (n4713 C++17 draft)
- The assignment operator (=) [...] The right operand is sequenced before the left operand.
因此行为已定义。 m.size()
将在 m[val]