向量:rend()被erase()无效

Mah*_*dsi 5 c++ vector erase visual-c++

根据C++规范(23.2.4.3),vector :: erase()只会使"擦除点之后的所有迭代器和引用"无效"

这样,在采用reverse_iterators时越过所有向量成员,在当前迭代器的擦除应该引起撕裂()成员将被无效.

此代码将在G ++下运行,但会在Windows上提供运行时异常(VS2010):

#include <vector>

using namespace std;

int main()
{
    vector<int> x;
    x.push_back(1);
    x.push_back(2);
    x.push_back(3);

    //Print
    for(vector<int>::const_iterator i = x.begin(); i != x.end(); ++i)
        printf("%d\n", *i);

    //Delete second node
    for(vector<int>::reverse_iterator r = x.rbegin(); r != x.rend(); ++r)
        if(*r == 2)
            x.erase((r+1).base());

    //Print
    for(vector<int>::const_iterator i = x.begin(); i != x.end(); ++i)
        printf("%d\n", *i);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误很有趣:

表达式:向量迭代器不可递减

在第二次运行时给出第二个for循环的行.递减引用reverse_iterator的内部"当前"迭代器成员,每当reverse_iterator递增时递减.

有人能解释一下这种行为吗?

谢谢.

编辑

我认为这个代码示例更好地表明它不是r的问题,而是rend():

//Delete second node
for(vector<int>::reverse_iterator r = x.rbegin(); r != x.rend();)
{
    vector<int>::reverse_iterator temp = r++;

    if(*temp == 2)
        x.erase((temp+1).base());
}
Run Code Online (Sandbox Code Playgroud)

并且vector iterators incompatible在擦除后进入for循环时出错.

asc*_*ler 4

您的程序调用未定义的行为。因此,这两个编译器都不正确。

根据标准,std::vector<int>::reverse_iterator是 的 typedef std::reverse_iterator<std::vector<int>::iterator>。的实现std::reverse_iterator<Iter>被指定为具有一个protected成员Iter current;,并且 的所有其他成员和函数reverse_iterator都是根据该成员的行为来指定的current

所以假设我们有r == reverse_iterator(i),其中i是一个有效的迭代器std::vector<int> x;。其中每一项都由标准保证。

r.current == i
(r+1).current == (i-1)
(r+1).base() == (i-1)
Run Code Online (Sandbox Code Playgroud)

在调用 时x.erase((r+1).base());,之后的所有迭代器都i-1将失效。当然,这包括i,因此也包括r.current

您的程序尝试评估的下一件事是++r。该表达式被指定为具有效果--r.current;。但既然r.current已经失效了,这个表达式就是Undefine Behaviour;也是如此++r