1

Josuttis の「The C++ Standard Library, 2nd ed.」を読んでいました。セクション 6.7.1 で、著者は、以下に示すコードが予期しない結果をもたらすと説明しています。std::remove()どのように機能するのか、なぜこの奇妙な結果が得られるのかはまだわかりません。std::erase()(実際に要素を削除するにはを使用する必要があることは理解していましたが、実際には& `std::remove() をlist::erase()組み合わせて使用​​するよりも使用した方がよいでしょう)。std::remove()

list<int> coll;
// insert elements from 6 to 1 and 1 to 6
for (int i=1; i<=6; ++i) {
     coll.push_front(i);
     coll.push_back(i);
}

// print
copy (coll.cbegin(), coll.cend(), // source
      ostream_iterator<int>(cout," ")); // destination
      cout << endl;

// remove all elements with value 3
remove (coll.begin(), coll.end(), // range
        3); // value
// print (same as above)   

結果は

pre:  6 5 4 3 2 1 1 2 3 4 5 6
post: 6 5 4 2 1 1 2 4 5 6 5 6 (???) 
4

4 に答える 4

4

この説明は役立つはずです:

削除は、消去する要素が上書きされるように、範囲内の要素をシフトすることによって行われます。残っている要素の相対的な順序は保持され、コンテナーの物理サイズは変更されません。範囲の新しい論理的な終わりと物理的な終わりの間の要素を指すイテレータは引き続き参照解除できますが、要素自体には未指定の値があります。通常、 remove の呼び出しの後にコンテナーの erase メソッドの呼び出しが続きます。これにより、指定されていない値が消去され、コンテナーの物理サイズが新しい論理サイズに一致するように縮小されます。

from の戻り値は、新しいendstd::remove()を表す反復子であることに注意してください。したがって、この新しい端と古い端を呼び出すと、余分なスペースが解放されます。std::erase()

于 2013-09-26T20:39:07.440 に答える
4

std::remove実際にはリストを短縮しません。コンテナ自体ではなくイテレータのみを取得するため、できません。

それが行うことは、残りの値をコピーして、コンテナーの先頭に取得することです。しかし、コンテナーの最後の要素 (あなたの場合 - 最後の 2 つ: '5' と '6') は実際にはまだそこにあります..

使用後は、残りの「ジャンク」コピーを削除するために、自分でコンテナに短縮するstd::remove必要があります。

于 2013-09-26T20:39:10.213 に答える