这些向量迭代是否相同?

时间:2016-04-07 08:23:05

标签: c++ vector iteration

Form 1

int main()
{
    std::vector<int> array{1, 2, 3, 4, 5};   

    for(auto i = array.begin(); i != array.end();) {      
        if(*i == 2 || *i == 5) {
            i = array.erase(i);
        } else {          
            i++;
        }
    }   
}

Form 2

int main()
{
    std::vector<int> array{1, 2, 3, 4, 5};   

    for(auto i = array.begin(); i != array.end(); i++) {
        if(*i == 2 || *i == 5) {
            i-- = array.erase(i);
        }
    }   
}

这两种形式是否相同?我可以使用一个或另一个来解决问题吗? (即对于各种对象,例如链表?)。

3 个答案:

答案 0 :(得分:4)

这一个,形式3:

#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> array{1, 2, 3, 4, 5};

    auto is_2_or_5 = [](int i) {
        return i == 2 || i == 5;
    };

    array.erase(std::remove_if(array.begin(),
                               array.end(),
                               is_2_or_5),
                array.end());

}

答案 1 :(得分:3)

i-- = array.erase(i);

C++11C++11之前都有未定义的行为。

有关更多血腥的详细信息,请查看:

即使它被很好地定义,我也不会将i--构造用于除独立表达式之外的任何其他内容。很难理解发生了什么。

答案 2 :(得分:2)

表格2 已损坏。

i-- = array.erase(i);

让我们打破它;

i--  

这将返回i的副本,然后递减i

array.erase(i) 

这会删除i处的元素,然后将迭代器返回到元素之后。

(i--) = (array.erase(i));

这会将array.erase(i)的结果分配给i--返回的副本。

在C ++ 11之前肯定会有一个额外的复杂因素,你不知道在调用array.erase(i)之前或之后是否完成了减量,这可能是未定义的行为。实验上,GCC在擦除之前执行递减,因此您最终会删除错误的元素。

编写(几乎)等效代码可能会有所帮助:

    auto j = i;
    --i;          // Here??
    auto k = array.erase(i);
    --i;          // Or here?
    j = k;

如果您想这样做,请将其写为:

    const auto j = i;
    --i;
    array.erase(j);

这使你更清楚自己在做什么。