迭代器有效性

时间:2016-11-28 03:13:58

标签: c++ c++11

我在这里寻找更深入的解释,而不仅仅是如何获得有效的代码。我知道如何编写更短的代码来擦除元素。我在这里写了这个测试代码,以确定删除时的失败点。似乎不仅i迭代器变得无效而且.end()迭代器......这很有趣。

为什么这有效?

    deque<shared_ptr<Vehicle>> data;
    data.push_back( shared_ptr<Vehicle>(new Vehicle("porsche")) );
    data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );
    data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );
    data.push_back( shared_ptr<Vehicle>(new Vehicle("bmw")) );
    data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );    

    auto end = data.end();
    for(auto i = data.begin(); i != end;)
    {

        if( (*i)->getName() == "fiat" )
        {
            auto ti = i;
            ++ti;
            end = data.end();   //above erase, works but not logical
            data.erase(i);
            i=ti;
        }
        else
        {
           ++i;
           end = data.end();
        }
    }

但这不起作用?

deque<shared_ptr<Vehicle>> data;
data.push_back( shared_ptr<Vehicle>(new Vehicle("porsche")) );
data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );
data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );
data.push_back( shared_ptr<Vehicle>(new Vehicle("bmw")) );
data.push_back( shared_ptr<Vehicle>(new Vehicle("fiat")) );    

auto end = data.end();
for(auto i = data.begin(); i != end;)
{

    if( (*i)->getName() == "fiat" )
    {
        auto ti = i;
        ++ti;
        data.erase(i);
        end = data.end();   //Bellow erase...more logical but crashes
        i=ti;
    }
    else
    {
       ++i;
       end = data.end();
    }
}

我猜这里有一些实施水平问题。也许是编译器错误。使用GCC 4.8.2。

1 个答案:

答案 0 :(得分:0)

您正在调用未定义的行为。根据语言规范,约deque::erase

  

擦除deque的最后一个元素的擦除操作仅使过去结束无效   迭代器和所有迭代器以及对已擦除元素的引用。擦除操作,擦除   deque的第一个元素但不是最后一个元素只使迭代器和对擦除的引用无效   元素。擦除操作,既不擦除双端队列的第一个元素也不擦除双端队列的最后一个元素   使得过去的迭代器和所有迭代器以及对双端队列的所有元素的引用无效。

在你的情况下,你的end迭代器总是被破坏,它只是运气,它完全有效。第二种情况下的崩溃可能是由于i上的操作,而不是data.end来电。