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