1

リストをそれ自体とスプライシングする際に問題に直面しています。std::list で splice() とイテレータの無効化を行ったことに注意してください。ここで の質問は、2 つの異なるリストに関するものでした。しかし、私の質問は同じリストについてです。

mylist.splice(mylist.end(), mylist, ++mylist.begin());

gcc 3.x が移動したイテレータを無効にしているようです。したがって、ノードの割り当てを解除して再度割り当てていると思います。これは、同じリストでは意味がありません。SGI は、このバージョンの splice がイテレータを無効にすべきではないと言っています。回避策がある場合、これは gcc 3.x のバグですか?

その間、私は stl_list.h ファイルを調べていました。しかし、transfer() 関数に固執したため、これらの定義が見つかりませんでした。

struct _List_node_base
  {
    _List_node_base* _M_next;   ///< Self-explanatory
    _List_node_base* _M_prev;   ///< Self-explanatory

    static void
    swap(_List_node_base& __x, _List_node_base& __y);

    void
    transfer(_List_node_base * const __first,
         _List_node_base * const __last);

    void
    reverse();

    void
    hook(_List_node_base * const __position);

    void
    unhook();
  };

これらの関数定義をどこで探すことができますか?

4

1 に答える 1

0

この関数は、ヘッダーではなく libstdc++ ソースにあります。3.4ではlibstdc++-v3/src/list.cc

http://gcc.gnu.org/viewcvs/branches/gcc-3_4-branch/libstdc%2B%2B-v3/src/list.cc?view=markup

でコンパイルしてみました-D_GLIBCXX_DEBUGか?これにより、デバッグ モードが有効になり、無効なイテレータを使用しているかどうか、または問題の原因となっているその他のものがあるかどうかがわかります。

デバッグモードの有無にかかわらず、GCC 3.4でこの簡単なテストを試したところ、うまくいきました:

#include <list>
#include <iostream>
#include <string>

int main()
{
  std::list<std::string> l;
  l.push_back("1");
  l.push_back("2");
  l.push_back("3");
  l.push_back("4");
  l.push_back("5");
  l.push_back("6");
  l.splice(l.end(), l, ++l.begin());

  for (std::list<std::string>::iterator i = l.begin(), e = l.end(); i != e; ++i)
    std::cout << *i << ' ';
  std::cout << std::endl;
}

さらに変更してデバッグすると、スプライスを実行するときに要素が破棄されたり再割り当てされたりしないことがわかります。そのため、プログラムにバグがあると思われます。問題が何であるかを実際に言っていないので、知るのは難しいです。

于 2012-05-07T02:49:29.223 に答える