开发者

std::list erase incompatible iterator

开发者 https://www.devze.com 2023-03-02 17:46 出处:网络
I have list with objects. I get some items from that list and do something with items. If work is done without errors i wish to delete these items from list. After that, on erase I get exception of in

I have list with objects. I get some items from that list and do something with items. If work is done without errors i wish to delete these items from list. After that, on erase I get exception of incompatible iterator. I understand that tmp is different list. But how to solve this problem?

#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_ba开发者_Python百科ck(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 not always get full list. It can copy part of list, so i don't want clear whole list.


You can't erase from one list using iterators from another list. An iterator "points" to some node in a list. Its pointing to something in a specific list. When you copy those things into another list, you have two lists with two sets of nodes now. Your iterator points to only one of those copies, not to both.

In the program as it is, the std::list destructor will cause your list to cleanup, so you don't even need to do an explicit clear.

As others have said, you can use clear to blow away the contents of the list. But I'm not 100% sure thats what you mean to do. Do you mean to erase all the contents of list that are also in tmp? If that's the case, then you may wish to use remove_if with a predicate

 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());
 }


I think you wanna clear your list, use, list.clear() Also, in your code:

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

is wrong! I think you meant:

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


You're trying to erase from list using iterators for tmp - that makes no sense, what would be erased?

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

or, just list.clear();


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

Typo!

I think you wanted to type:

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

The reason why you get error, because you cannot delete elements from one list using iterator range obtained from another list. Iterator obtained from one list is unreachable from iterator obtained from another list.


I have idea with using boost::iterator_range. Its saves range for later delete. Is it ok?

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());


It sounds like your problem is similar to the one in Can you remove elements from a std::list while iterating through it?. You could probably use a similar solution.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号