4

「 list::splice 」がどのように機能するかを読んでいますが、何かがわかりません。

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)

  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  it = mylist1.begin();
  std::advance(it,3);           // "it" points now to 30

  mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                                // mylist1: 30 3 4 1 10 20

1番目と3番目のスプライスでは、itイテレータは引き続き有効ですが、2番目のスプライスではなぜそうではないのでしょうか。

ドキュメントによると:

イテレータの有効性

呼び出し前に、コンテナーに関連するイテレーター、ポインター、および参照に変更はありません。転送された要素を参照するイテレーター、ポインター、および参照は、同じ要素を参照し続けますが、イテレーターは、要素が転送されたコンテナーを反復処理するようになりました。

したがって、それはまだ有効であるはずです

4

2 に答える 2

4

これは単なる推測ですが、それがの有効なイテレータではなく、代わりにの有効なイテレータになるitという意味で、これが「無効」になったことを意味すると書いている可能性があります。mylist1mylist2

しかし、それでも、あなたはすでにそれを知っていると思いますが、それは有効なイテレータであるため、言い回しは誤解を招きます。ただし、注意する必要があります。これは、たとえば2回目のスプライス操作の後、次のことができなくなることを意味します。

std::distance( mylist1.begin(), it );

しかし、使用する必要があります

std::distance( mylist2.begin(), it );

最初のものは違法だろうから。

この規格では、次のように明確に定義されています。

23.3.5.5リスト操作[list.ops]

void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);

7 効果:iリストからポイントされた要素をx前に挿入し、要素をpositionから削除しxます。position == iまたはの場合、結果は変わりませんposition == ++i*iこの同じ要素を引き続き参照するためのポインタと参照。ただし、のメンバーとして*this*i(それ自体を含む)へのイテレータiは引き続き同じ要素を参照しますが*this、ではなく、へのイテレータとして動作するようになりましxた。

したがって、コンパイラ/ STLがイテレータを無効にする場合、これは明らかにバグです。

于 2013-03-25T10:52:13.687 に答える
1

どうやら(私はMSVC2012を使用しているので)動作は異なります:

http://msdn.microsoft.com/en-us/library/72fb8wzd.aspx

すべての場合において、スプライスされた要素を指すイテレータまたは参照のみが無効になります。

したがって、あるコンテナから別のコンテナに移動する要素へのイテレータがある場合、これらのイテレータは無効になります。

ただし、この動作が標準的な動作であるかどうかを知りたいと思います。

于 2013-03-25T11:15:24.927 に答える