C++ 此递减的顺序是否调用未定义的行为?
我正在寻找确认,澄清是这个代码定义良好与否 通过将迭代器重新分配给容器的C++ 此递减的顺序是否调用未定义的行为?,c++,stl,containers,undefined-behavior,erase,C++,Stl,Containers,Undefined Behavior,Erase,我正在寻找确认,澄清是这个代码定义良好与否 通过将迭代器重新分配给容器的erase()函数的结果,在循环中擦除容器的元素是非常常见的。循环通常有点混乱,如下所示: struct peer { int i; peer(int i): i(i) {} }; int main() { std::list<peer> peers {0, 1, 2, 3, 4, 5, 6}; for(auto p = peers.begin(); p != peers.end();) //
erase()
函数的结果,在循环中擦除容器的元素是非常常见的。循环通常有点混乱,如下所示:
struct peer { int i; peer(int i): i(i) {} };
int main()
{
std::list<peer> peers {0, 1, 2, 3, 4, 5, 6};
for(auto p = peers.begin(); p != peers.end();) // remember not to increment
{
if(p->i > 1 && p->i < 4)
p = peers.erase(p);
else
++p; // remember to increment
}
for(auto&& peer: peers)
std::cout << peer.i << ' ';
std::cout << '\n';
}
结构对等体{inti;对等体(inti):i(i){};
int main()
{
std::列出对等点{0,1,2,3,4,5,6};
for(auto p=peers.begin();p!=peers.end();)//记住不要递增
{
如果(p->i>1&&p->i<4)
p=对等点。擦除(p);
其他的
++p、 //记住要递增
}
用于(自动和对等:对等)
标准::cout i<4)
--(p=peers.erase(p));//惯用减量???
用于(自动和对等:对等)
std::cout这取决于检测要删除的元素时使用的条件。如果尝试删除第一个元素,则会失败,因为
erase
将返回新的begin()
,然后将其递减,即使立即再次递增
为了避免这个错误,并且因为它更常见、更可读,我会坚持使用第一个版本。这取决于您用来检测要删除的元素的条件。如果您尝试删除第一个元素,它将失败,因为
擦除
将返回新的开始()
然后将其递减,即使立即再次递增
为了避免这个错误,并且因为它更常见、更易读,我坚持使用第一个版本。第二个版本是错误的,正如@DanielFrey所说的,但是如果你不喜欢第一个版本,为什么不这样做呢:
std::list<int> myList = { 0, 1, 2, 3, 4, 5, 6 };
myList.remove_if(
[](int value) -> bool {
return value > 1 && value < 4;
}
);
/* even shorter version
myList.remove_if([](int value) -> bool {
return (value > 1 && value < 4);
});
*/
for(int value : myList) {
std::cout << value << " ";
}
.正如@DanielFrey所说,第二个版本是错误的,但如果你不喜欢第一个版本,为什么不这样做呢:
std::list<int> myList = { 0, 1, 2, 3, 4, 5, 6 };
myList.remove_if(
[](int value) -> bool {
return value > 1 && value < 4;
}
);
/* even shorter version
myList.remove_if([](int value) -> bool {
return (value > 1 && value < 4);
});
*/
for(int value : myList) {
std::cout << value << " ";
}
.我会坚持使用第一个版本-它对一个开始更具可读性-排序方面没有问题,因为这些是重载运算符-即函数调用。我会坚持使用第一个版本-它对一个开始更具可读性-排序方面没有问题,因为这些是重载运算符-即函数调用。是的,我我刚刚检查过这一点,它在标准中是绝对不允许的。是的,我刚刚检查过这一点,它在标准中是绝对不允许的。这是一个好主意。不幸的是,有时你想根据不同的条件做一些不同的事情-有时擦除,有时调用成员函数等等在某些情况下,您需要自己进行循环。@Galik-(1)OP的示例都是关于删除特定项的,所以…;)(2)看一看-您也可以修改值。如果要删除此值,请返回true,如果不删除此值,请返回false。否则,这相当好地充当容器迭代器,为每个项调用自定义函数。这是一个好主意。不幸的是,有时您需要根据差异执行许多不同的操作不同的条件-有时删除,有时调用成员函数等…。在这些情况下,您需要自己执行循环。@Galik-(1)OP的示例都是关于删除特定项的,所以…;)(2)看一看-您也可以修改值。如果要删除此值,只需返回true,如果不删除此值,则返回false。否则,这相当于为每个项调用自定义函数的容器迭代器。
0 1 4 5 6