1

重複の可能性:
STL削除が期待どおりに機能しませんか?

申し訳ありませんが、C++11とイテレータは初めてです。これにより、配列内の3の数字がすべて削除されるはずですが、最後の3は削除されません。なんで?

#include <algorithm>
#include <array>
#include <iostream>

int main() {

   std::array<int, 8> a{{9, 3, 4, 5, 33, 5, 6, 3}};

   int N(3);

   std::remove(a.begin(), a.end(), N);

   for (int i : a) {
      std::cout << i << '\n';
   }

}

私は出力として取得します:

{ 9, 4, 5, 33, 5, 6, 6, 3 }
                        ^
                        |
             // the last 3 is still there
4

3 に答える 3

6

std::removeイテレータで動作します。そのため、コンテナから要素を実際に消去する方法はありません。それが一般的に一緒に使用される理由eraseです:

a.erase(std::remove(a.begin(), a.end(), N), a.end());

他の人が指摘しているように、これはでは機能しませんarray

于 2012-12-30T20:51:07.220 に答える
6

アルゴリズムには、基礎となるコンテナに関する知識がありません。それらは、与えられたイテレータに基づいて反復し、それらを保持しているコンテナとは無関係に要素にアクセスします。そのため、 erase-removeイディオムと呼ばれるものがあり、次のパターンを取ります。

container.erase(std::remove(it1, it2, value), std::end(container));

std::remove保持されている要素を前面に移動し(ありがとう、K-ballo)、移動されていない要素の先頭にイテレータを戻します。次に、eraseその時点から最後まですべてを消去します。

std::array固定サイズの配列をカプセル化するので、次の例を採用しstd::vectorます。

std::vector<int> v{9, 3, 4, 5, 33, 5, 6, 3};
v.erase(std::remove(std::begin(v), std::end(v), 3), std::end(v));

注意すべき他の唯一のことは、より一般的な形式の.begin()andであり.end()、これは組み込み配列でも機能します。これはC++11に含まれています。

于 2012-12-30T20:51:17.587 に答える
2

他の人が指摘したようにstd::remove()、要素を削除しません。使用する必要がある場合std::array<...>でもstd::remove()、対応するイテレータを使用してキャプチャし、シーケンスの終了を判別できます。要求された出力(カーリーとコンマを含む)をどのように取得したかはわかりませんが、次のように実装します。

auto end = std::remove(a.begin(), a.end(), 3);
std::cout << "{ ";
if (a.begin() != end) {
    std::copy(a.begin(), end - 1, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << end[-1];
}
std::cout << "}\n";
于 2012-12-30T21:02:32.547 に答える