【发布时间】:2013-11-01 23:47:20
【问题描述】:
Accordint to this quite highly upvoted answer,遍历集合擦除某些元素的规范方法如下:
for (it = mySet.begin(); it != mySet.end(); ) {
if (conditionToDelete(*it)) {
mySet.erase(it++);
}
else {
++it;
}
}
这当然是 C++03 的 set erase 没有返回迭代器的结果。不然可以写it = mySet.erase(it); 也很明显可以写
itToDelete = it++;
mySet.erase(itToDelete);
这个问题不是关于如何在迭代时删除元素。问题是为什么下面这行显然 not 会导致未定义的行为。
mySet.erase(it++);
起初我确定这一定是 UB,因为我对后增量的看法是错误的。这是一种常见(但错误)的方式,将预增量视为在其余评估之前发生,而后增量发生在之后。当然,这是错误的。 postincrement 和 preincrement 都有增加变量的副作用。区别在于这些表达式的值。
也就是说,据我所知,C++ 标准(至少是 C++03 标准)没有具体说明后增量的副作用何时发生。所以,除非我们有保证,如果作为后增量表达式的函数参数在进入函数体之前会产生副作用,这不应该是UB吗?究竟是什么(标准方面)(如果有的话)禁止在迭代器在函数体内失效后发生 it++ 的副作用?
非常欢迎引用标准。
为了论证,我们还假设 set 的迭代器是一个内置类型,这实际上是 operator ++,而不是重载的 operator-function
【问题讨论】:
-
标准不要求在控制流进入被调用函数的主体之前评估所有函数参数吗?
-
@H2CO3:评估某事是否涉及所有副作用的发生?
-
我很确定确实如此,但我正在检查标准。
标签: c++ iterator c++03 post-increment side-effects