2009-03-19 4 views
10

私はちょうどがfind,searchと一緒に非修正シーケンス操作であることをC++標準で読みました。それは、各要素に適用された関数がそれらを変更すべきではないということですか?何故ですか?おそらく何がうまくいかないでしょうか?std :: for_eachが非変更シーケンス操作であるのはなぜですか?

ここでは、シーケンスが変更されたサンプルコードを示します。あなたはそれに間違って何かを見ることができますか?

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:for_eachの代わりにstd::transformを使用することができますが、それは重要なことではありません。

答えて

16

は、彼らが

LWGが標準で何が配列要素を変更する関数オブジェクトを禁止していないと信じていると言うthis defect report参照してください。問題は、for_eachが "nonmutating algorithms"というタイトルのsecionにあり、タイトルが混乱している可能性があるということです。非定型の注記でそのことを明確にする必要があります。

でも、注記this one

for_each自体が明示的にシーケンスの要素を変更しないため、それらは「非変更」と呼ばれるようです。 litbとして

+0

はい、同じ問題リストが見つかりました。私が推測したように、それは単なる解釈の問題でした(しかし、私は本当に彼らがこの明確な注釈を加えるべきだと考えています)。 –

+0

ええ、私も思う。まだn2800にはありません。次のドラフトが何を含んでいるかを見てみましょう。ノートにはCD1のステータスがあるので、それはもう奇妙です。私は彼らがそれをコンセプトにしたいので、彼らはそれを削除した疑いがあります。 –

+0

ニースが見つかりました!特に、欠陥報告書にこれを書き留めておきます。「StepanovとLeeによるオリジナルのSTLドキュメントは、関数オブジェクトがその引数を変更することを明示的に禁止しました。私はそれを知らなかった。 –

20

まったく単純に、コンテナの構造を変更することはできません。一般的なケースでは、コンテナを変更すると、使用されているイテレータが無効になる可能性があるからです。

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

for_eachは「非修正」アルゴリズムであることについていくつかの混乱があるように思われることを[追加]


注意。この混乱する状況は、Stroustrupが第4回「The C++ Programming Language、3rd Ed。」の正誤表で要約したものです。 (CPL)は、このfor_eachは、シーケンス(http://www.research.att.com/~bs/3rd_printing5.html)の要素を変更できるかどうかについて言いたいことがあります。それは、明示的に順序を変更しないので、

は「for_each()アルゴリズムがnonmodifyingとして分類されているが、場合。非constシーケンスに適用されます。for_each()は、シーケンスの要素を変更することがあります。例については、11.9のnegate()の使用を参照してください。 (最近の標準の解決)。

CPLは、もともと、for_eachに渡された関数または関数オブジェクトが、渡された要素の変更を許可されていないことを示しました。しかし、CPLは規格が完成する前に書かれ、もともと公開されており、最終的に確定される前にこの制限が明らかに取り除かれました。

も参照してください:

6

私は、この操作は、を変更しないことを意味し、 "シーケンス操作を無修正" だと思います配列。しかし、操作は、コンテナ要素を変更できます。

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

2

は、それに対応する「変異」「nonmutatingアルゴリズム」

STLのは、STDであるとして:: for_each変換が分類され、上記で示しました。

あなたがstd :: transformを使用できることを知っておられたので、上記は本当にポイントになります。あなたのコードを読んでいる人たちとのコミュニケーションの場として役立ちます。

私がstd :: for_eachを見ると、fooがどんなことをしてもコンテナは変更されないことは明らかです。

私は従うガイドラインを述べることができる:

「あなたはSTDを使用して、要素を変更しないいくつかのタスクを実行するために、コンテナの要素を使用したい場合:: for_each

あなたの場合。コンテナの要素をシステム全体のやり方で変更したり、何らかの方法で変更するタスクで使用したりするには、std :: transformを使用してください。

関連する問題