C++ 为什么不是';t mySet.erase(它是未定义的行为,还是?
据此,通过删除某些元素来迭代集合的规范方法如下:C++ 为什么不是';t mySet.erase(它是未定义的行为,还是?,c++,iterator,c++03,post-increment,side-effects,C++,Iterator,C++03,Post Increment,Side Effects,据此,通过删除某些元素来迭代集合的规范方法如下: for (it = mySet.begin(); it != mySet.end(); ) { if (conditionToDelete(*it)) { mySet.erase(it++); } else { ++it; } } 当然,这是C++03的set erase没有返回迭代器的结果。否则就可以写it=mySet.erase(它)很明显,一个人可以写 itToDelete
for (it = mySet.begin(); it != mySet.end(); ) {
if (conditionToDelete(*it)) {
mySet.erase(it++);
}
else {
++it;
}
}
当然,这是C++03的set erase没有返回迭代器的结果。否则就可以写it=mySet.erase(它)代码>很明显,一个人可以写
itToDelete = it++;
mySet.erase(itToDelete);
这个问题不是关于如何在迭代时删除元素。问题是,为什么下面这一行显然不会导致未定义的行为
mySet.erase(it++);
起初我确信这一定是UB,因为我对后增长的想法是错误的。将预增量视为在其余评估之前发生,而将后增量视为在其他评估之后发生,这是一种常见(但错误)的方式。当然,这是错误的。增量后和增量前都有增加变量的副作用。区别在于这些表达式的值
这是,据我所记得的,C++标准(至少C++ 03)没有确切地说明PASTY增量的副作用何时发生。所以,除非我们有一个保证,如果一个函数参数,它是一个后增量表达式,在进入函数体之前会有它的副作用,这不应该是UB吗?在函数体中迭代器失效后,到底是什么(标准方面)阻止了it++的副作用呢
非常欢迎从标准中引用
为了参数起见,我们还假设集合的迭代器是内置类型,它实际上是运算符++,而不是重载的运算符函数这不在C++03中,因为在计算所有函数参数之后有一个序列点
最接近C++03的标准草案是公开的,我找不到以前的标准草案的公开版本,但使用了C++98和C++03作为参考,短语与N1804中的以下段落一致
在1.9节中
程序执行第16段说(重点放在后面):
调用函数时(无论函数是否为内联函数),在执行函数体中的任何表达式或语句之前,所有函数参数的求值后都会有一个序列点。[……]
在后面的5.2.2节中
函数调用第8段说:
未指定参数的求值顺序参数表达式求值的所有副作用在输入函数之前生效。未指定后缀表达式和参数表达式列表的求值顺序
标准难道不要求在控制流进入被调用函数体之前对所有函数参数进行求值吗?@H2CO3:求值是否涉及其所有副作用的发生?我很确定它会,但我正在检查标准。