11

などと一緒に、std::for_each非変更シーケンス操作である C++ 標準を読み込んだところです。それは、各要素に適用された関数がそれらを変更してはならないということですか? 何故ですか?何がうまくいかない可能性がありますか?findsearch

シーケンスを変更したサンプル コードを次に示します。何か問題があることがわかりますか?

void foo(int & i)
{
    i = 12;
}

int main()
{
    std::vector<int> v;
    v.push_back(0);

    std::for_each(v.begin(), v.end(), foo);
    // v now contains 12
}

これは単なる解釈の問題だと思いますが、それについてあなたの意見を聞きたかったのです。

PS:のstd::transform代わりに使用できることはわかっていますがfor_each、それは重要ではありません。

4

4 に答える 4

21

簡単に言えば、コンテナーの構造を変更する可能性のある変更を行うことはできません。これは、一般的に、コンテナーを変更すると、使用されている反復子が無効になる可能性があるためです。

コンテナーの構造 (コンテナー内の要素の順序など) を変更しない限り、要素を変更できます。

[添加]


for_each「非変更」アルゴリズムであることについて、いくつかの混乱があるように思われることに注意してください。この紛らわしい状況は、「C++ プログラミング言語、第 3 版」の第 4 版の正誤表で Stroustrup によってここに要約されています。( CPL ) はfor_each、シーケンスの要素を変更できるかどうかについて次のように述べています ( http://www.research.att.com/~bs/3rd_printing5.html ):

「このfor_each()アルゴリズムは、シーケンスを明示的に変更しないため、非変更として分類されます。ただし、非 const シーケンスに適用するとfor_each()、シーケンスの要素が変更される可能性があります。例についてはnegate()、11.9 での使用を参照してください。」(最近の標準決議)。

CPL は元々、渡された関数または関数オブジェクトが、for_each渡された要素を変更することを許可されていないことを示していました。ただし、CPL は、標準が最終化される前に作成され、最初に公開されたものであり、明らかに、この制限は最終化for_each()される前に削除されました。

以下も参照してください。

于 2009-03-19T16:12:11.863 に答える
6

「非変更シーケンス操作」とは、この操作がシーケンスを変更しないことを意味すると思います。ただし、操作によってコンテナ要素が変更される可能性があります

コンテナ要素とシーケンスの値 - 異なるもの。

于 2009-03-19T16:16:35.427 に答える
2

上記の litb のように、for_each は「不変アルゴリズム」に分類されます。

それに対応する STL の「変更」は std::transform です。

あなたが std::transform を使用できることを知っていることを示したので、上記は確かにポイントになります。これは、コードを読む人々へのコミュニケーションのポイントとして機能します。

std::for_each が表示された場合、foo が何をしても、コンテナーが変更されないことは明らかです。

私が従うガイドラインは次のとおりです。

「コンテナーの要素を使用して、要素を変更しないタスクを実行する場合は、std::for_each を使用します。

コンテナーの要素を使用して、何らかの体系的な方法で要素を変更したり、何らかの方法で変更するタスクでそれらを使用したりする場合は、std::transform を使用してください。」

于 2009-03-19T21:49:50.727 に答える