• Lerosua on Twitter

    t
  • 订阅

    抓虾
    google reader
    bloglines
    鲜果
  • 分类目录

  • 功能

  • « | Main | »

    for循环中iterator不可乱删除

    By lerosua | 八月 19, 2007

    今天写iTalk,想要把空组删除掉。
    //tree_store就是列表中的数据(TreeStore)
    //下面代码作用是扫描列表中的组,发现空组则删除。
    Gtk::TreeModel::Children children = tree_store->children();
    Gtk::TreeModel::iterator it_g;
    it_g = children.begin();

    for (; it_g != children.end(); ++it_g) {
    Gtk::TreeModel::Children grandson = it_g->children();
    if(grandson.begin()==grandson.end())
    {
    const Glib::ustring& tmp= (*it_g)[buddyColumns.id];
    std::cout<<tmp<<”为空组=======================”<<std::endl;
    tree_store->erase(it_g);
    }
    }

    不过遇到了段错误。思前想后发现段错误的原因是因为那个删除 tree_store->erase(it_g);
    执行了这句后,it_g所指向的数据已经失效,所以it_g++的话就会溢出。
    把for 循环改成do while循环,用一个中间变量来得到it_g的值,并用它来删除。

    do{
    Gtk::TreeModel::Children grandson = it_g->children();
    Gtk::TreeModel::iterator point = it_g;
    it_g++;
    if(grandson.begin()==grandson.end())
    {
    //const Glib::ustring& tmp= (*point)[buddyColumns.id];
    //std::cout<<tmp<<”为空组=======================”<<std::endl;
    tree_store->erase(point);
    }

    }
    while(it_g!=children.end());
    嗯。这样也算是解决问题吧。

    Topics: 未分类 | 3 Comments »

    3 Responses to “for循环中iterator不可乱删除”

    1. zlbruce Says:
      八月 20th, 2007 at 4:13 上午

      erase()会返回下一行的iterator,或者end();所以直接it_g = tree_store->erase(it_g);去掉for中的++it_g就可以了。
      貌似grandson.empty()要好理解先吧

    2. lerosua ' blog Says:
      八月 21st, 2007 at 1:50 上午

      经过zlbruce提醒,代码已经精简:

      while(it_g!=children.end()){
      Gtk::TreeModel::Children grandson = it_g->children();
      if(grandson.empty())
      it_g = tree_store->erase(it_g);
      else
      it_g++;
      }

    3. google老犁 Says:
      八月 27th, 2007 at 1:38 上午

      erase(iterator)会删除这个位置上的元素,所以当你调用erase(iterator)时,那么iterator位置上的元素会被删除,iterator所指的元素位置也就无效了,编译不会出错(要想编译出错的话,使用安全STL,如STL port)。所以最优雅的解决的方法是erase(iterator++),删除了当前位置的元素,iterator的位置向下移动了,所以就不会出现段错误的情况了。

      考虑:
      erase(iterator++)

      erase(++iterator)
      这两者的区别.