2

同様に、単一リンクリストがあるとしますstd::forward_list述語に一致する単一のリスト要素を見つけ、それに対していくつかの操作を実行し、オプションで別の述語に基づいてそれを削除したいと思います。

これまでに、私は以下を組み立てました:

for (T::iterator it = l.begin(), prev_it = l.before_begin();
        it != l.end();)
{
    if (predicate)
    {
        // ...

        if (another_predicate)
        {
            l.erase_after(prev_it);
            break;
        }
    }

    prev_it = it;
    ++it;
}

ただし、インクリメント部分を実行するのに最適な方法かどうかは特に疑問です。あるいは、私は検討してきました:

    ++prev_it;
    ++it;

プレーンCでは前者の方が明らかに優れていますが、C++ではもうそれほど明確ではないようです。より単純なイテレータを使用すると、前者の方が単純になるはずです。ただし、イテレータのコピーにメモリ割り当てが含まれる場合(たとえば、PImplを使用する場合)、実際には後者の方が適している場合があります。

どの方法が優れていると思いますか、またその理由は何ですか?std::forward_listこれを厳密に一般的な設計に限定することを避け、より複雑なタイプで機能するソリューションを検討したいことに注意してください。

4

2 に答える 2

4

forループがカウンターをインクリメントしないと、私は本当に混乱するので、単に++prev_it, ++itforループに追加します。イテレータはロックステップにとどまり(イテレータをいじらない限り)、名前はそれらが何を指しているかを明確に示しています。パフォーマンスを心配する前に、私は常に明快さの側で誤りを犯します。

std::forward_listこれは特殊なケースであるため、このコードを他のコンテナーに一般化することについて心配する必要はありません。他のコンテナはのようなものを必要としませんerase_after

于 2012-08-17T17:58:07.343 に答える
2

明らかなassign-then-incrementの代わりに2つの増分で記述した場合、将来のすべてのメンテナは、何が欠落しているのか、なぜそのように記述されているのか疑問に思って、しばらくの間コードを凝視します。

明白な方法でコーディングする必要があります(前に保存してからインクリメントします)。プロファイリングで問題があることが示されている場所でイテレーターをコピーするのに費用がかかる場合は、より適切なイテレーターを見つけてください。通常、パフォーマンスに目立った影響を与えない可能性のある問題を回避するために、このようなコード変更を行うべきではありません。

編集:@Kerrek SBが質問へのコメントで述べているように、あなたは自分の意味について少し嘘をついていることに満足しているので、forward_list::remove_ifこれを実装するために(慎重に)ステートフルな述語で使用することもできます。

于 2012-08-17T17:43:56.437 に答える