std :: list стереть несовместимый итератор - PullRequest
2 голосов
/ 03 мая 2011

У меня есть список с объектами.Я получаю некоторые предметы из этого списка и что-то делаю с ними.Если работа сделана без ошибок, я хочу удалить эти элементы из списка.После этого при стирании я получаю исключение несовместимого итератора.Я понимаю, что TMP другой список.Но как решить эту проблему?

#include <list>

class A
{
public:
    A(int i):i_(i){}
private:
    int i_;
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::list<A> list;
    A a(1), b(2), c(3);
    list.push_back(a);
    list.push_back(b);
    list.push_back(c);

    std::list<A> tmp;
    tmp.insert(tmp.end(), list.begin(), list.end());
    // do something with tmp
    // if all is ok, then erase what is done
    list.erase(tmp.begin(), tmp.end());

    return 0;
}

tmp.Insert не всегда заполняется list.Он может копировать часть list, поэтому я не хочу очищать целое list.

Ответы [ 6 ]

6 голосов
/ 03 мая 2011

Вы не можете удалить из одного списка, используя итераторы из другого списка.Итератор "указывает" на некоторый узел в списке.Это указывает на что-то в определенном списке .Когда вы копируете эти вещи в другой список, у вас есть два списка с двумя наборами узлов.Ваш итератор указывает только на одну из этих копий, а не на обе.

В самой программе деструктор std::list приведет к очистке списка, поэтому вам даже не нужно делать явныеclear.

Как уже говорили другие, вы можете использовать clear , чтобы удалить содержимое списка.Но я не уверен на 100%, что ты собираешься делать.Вы хотите стереть все содержимое списка, который также есть в tmp?Если это так, то вы можете использовать remove_if с предикатом

 class CIsContainedInOtherList
 { 
 private:
     const std::list<int>& m_list;
 public:
      CIsContainedInOtherList(const std::list<int>& list);

      // return true if val is in m_list
      bool operator()(const int& val) const
      {
          std::list<int>::const_iterator iter 
             = std::find(m_list.begin(), m_list.end(), val);
          return (iter != m_list.end())
      }
 }

 int main()
 {
      ...
      CIsContainedInOtherList ifInOtherList(tmp);
      std::list<int>::iterator iter = 
              remove_if(list.begin(), list.end(), ifInOtherList);
      // remove everything that matched the predicate
      list.erase(iter, list.end());
 }
0 голосов
/ 03 мая 2011

Похоже, ваша проблема похожа на проблему в Можете ли вы удалить элементы из списка std :: list, просматривая его? . Возможно, вы могли бы использовать подобное решение.

0 голосов
/ 03 мая 2011

У меня есть идея с использованием boost :: iterator_range. Сохраняет диапазон для последующего удаления. Это нормально?

typedef std::list<A>::iterator AIter;

std::list<A> tmp;
boost::iterator_range<AIter>  range(list.begin(), list.end());
tmp.insert(tmp.end(), range.begin(), range.end());

list.erase(range.begin(), range.end());
0 голосов
/ 03 мая 2011

Вы пытаетесь удалить из list, используя итераторы для tmp - не имеет смысла, что будет стерто?

 list.erase(list.begin(), list.end());

или просто list.clear();

0 голосов
/ 03 мая 2011
  list.erase(tmp.begin(), tmp.end());
//^^^^

Опечатка!

Я думаю, что вы хотели ввести:

  tmp.erase(tmp.begin(), tmp.end());
//^^^^

Причина, по которой вы получаете ошибку, потому что вы не можете удалить элементы из одного списка, используя диапазон итераторов, полученный издругой список.Итератор, полученный из одного списка, недоступен от итератора, полученного из другого списка.

0 голосов
/ 03 мая 2011

Я думаю, что вы хотите очистить свой список, использовать, list.clear () Также в вашем коде:

list.erase(tmp.begin(), tmp.end());

не так! Я думаю, что вы имели в виду:

list.erase(list.begin(), list.end());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...