2016-11-28 58 views
0

我在这里寻找更深入的解释,而不仅仅是如何获得工作代码。我知道如何编写更短的代码来擦除元素。我在这里写了这个测试代码,以查明删除后的失败点。似乎不仅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。

+0

您可能在代码中的其他地方存在导致未定义行为的错误。您需要编辑您的问题并提供[mcve]。 –

+0

迭代器行为因容器类型而异。 “数据”究竟是什么? – 1201ProgramAlarm

+0

已添加代码。保证没有错误别的地方。即。班车正常实施等等。我不会发布它以保持代码的专注和清洁。 – code

回答

0

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

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

在你的情况,你的end迭代器总是越来越重挫,它只是运气,它在所有工作。在第二种情况下的崩溃很可能是由于i的操作,而不是data.end的呼叫。