5

std::remove_if は常に (反復子の順序に従って) 各要素の述語を順番に呼び出しますか、それとも順不同で呼び出される可能性がありますか?

これが私がやりたいことのおもちゃの例です:

void processVector(std::vector<int> values)
{
    values.erase(std::remove_if(values.begin(), values.end(), [](int v)
    {
        if (v % 2 == 0)
        {
            std::cout << v << "\n";
            return true;
        }
        return false;
    }));
}

特定の基準を満たすベクトルのすべての要素を処理して削除する必要があり、erase + remove_if はそれに最適なようです。ただし、これから行う処理には副作用があり、処理が順番どおりに行われるようにする必要があります (おもちゃの例で、元のベクトルに表示される順序で値を出力するとします)。

私の述語が各項目で順番に呼び出されると想定しても安全ですか?

C++17 の実行ポリシーによってこれが明確になると思いますが、C++17 はまだリリースされていないため、明らかに役に立ちません。

編集:また、これは良い考えですか?または、これを達成するためのより良い方法はありますか?

4

2 に答える 2

9

標準では、述語を呼び出す順序は保証されていません。

使うべきものはstable_partition. 述語に基づいてシーケンスを分割します。次に、分割されたシーケンスをウォークして、実行したい「副作用」を実行できます。これstable_partitionは、両方のデータ セットの相対的な順序が保証されるためです。次に、 から要素を消去できますvector

stable_partitionerase_if「消去された」要素の内容が未定義のままになるため、ここで使用する必要があります。

コード内:

void processVector(std::vector<int> &values)
{
    auto it = std::stable_partition(begin(values), end(values), [](int v) {return v % 2 != 0;});

    std::for_each(it, end(values), [](int v) {std::cout << v << "\n";});

    values.erase(it, end(values));
}
于 2016-08-08T23:00:25.117 に答える
-1

それらは順番に処理される必要がありますが、保証されていませ

std::remove_if()erase()は「削除された」アイテムをコンテナの最後に移動しますが、実際には が呼び出されるまでコンテナから削除されません。どちらの操作も、 内の既存の反復子を無効にする可能性がありstd::vectorます。

于 2016-08-08T23:02:32.213 に答える