5


1

シーケンスがあります。

std :: vector <Foo> someVariable;

そして私はその中のすべてを反復するループが欲しいのです。

私はこれをすることができます:

(int i = 0; iの場合

または私はこれを行うことができます:

for(std :: vector <Foo> :: iterator i = someVariable.begin(); i!= someVariable.end(); i){blah(i-> x、i-> y);ウープ(i  - > z); }

どちらもかなりの繰り返し/過度のタイピングを伴うようです。 理想的な言語で、私はこのようなことができるようになりたいです。

for(i in someVariable){blah(i-> x、i-> y);ウープ(i  - > z); }

シーケンス内のすべてを反復処理するのは、非常に一般的な操作になるでしょう。 コードが本来あるべき長さの2倍ではないようにする方法はありますか?

6 Answer


12


標準ライブラリの for_each`を使うことができます。 あなたはそれにファンクターや関数を渡すことができます。 私が好きな解決策は `BOOST_FOREACH`です。これは他の言語の foreach`のようなものです。 C 0xは一方で2つ持っているつもりです。

例えば:

#include #include #include #include

#define foreach BOOST_FOREACH

void print(int v){std :: cout << v << std :: endl; }

int main(){std :: vector配列;

(int i = 0; i <100; i){array.push_back(i); }

std :: for_each(array.begin()、array.end()、print); // STLを使用

foreach(int v、array)// Boostを使う{std :: cout << v << std :: endl; }}


5


AraKがすでに提案したBOOST_FOREACHを数えないで、今日のCには次の2つの選択肢があります。

void関数(Foo

std :: for_each(someVariable.begin()、someVariable.end()、関数);

struct functor {void operator()(Foo

std :: for_each(someVariable.begin()、someVariable.end()、functor());

どちらも、関数またはファンクタ( `operator()をオーバーロードするクラス)として、他の場所でループの「本体」を指定する必要があります。 これは良いことです(複数のループで同じことを実行する必要がある場合は、関数を1回定義するだけで済みます)が、やや面倒になることもあります。 コンパイラは一般に関数呼び出しをインライン化できないため、関数バージョンは少し効率が悪くなることがあります。 (関数ポインタは3番目の引数として渡され、コンパイラはそれがどの関数を指しているかを判断するためにさらに詳細な分析を行わなければなりません。)

ファンクターバージョンは基本的にゼロオーバーヘッドです。 functor`型のオブジェクトは for_each`に渡されるので、コンパイラは呼び出すべき関数を正確に知っています: `functor

operator()`それは簡単にインライン化することができ、元のループと同じくらい効率的になります。

C 0xは3番目の形式を可能にするラムダ式を導入します。

std :: for_each(someVariable.begin()、someVariable.end()、[](Foo)

最後に、範囲ベースのforループも導入されます。

for(Foo

したがって、C 0xのサブセットをサポートするコンパイラにアクセスできれば、最後の形式の一方または両方を使用できます。 そうでなければ、(Boostを使わずに)慣用的な解決策は最初の2つの例のうちの1つのように `for_each`を使うことです。


1


手書きループへのアルゴリズム呼び出しを優先する

3つの理由があります。

1)*効率性:*アルゴリズムはプログラマーが作成するループよりも効率的です。

2)*正しさ:*ループを書くことは、アルゴリズムを呼び出すよりもエラーを受けやすいです。

3)*保守性:*アルゴリズム呼び出しは、対応する明示的なループよりも明確でわかりやすいコードを生成します。


1


ところで、MSVS 2008には "for each" Cキーワードがあります。 How to:STLコレクションを繰り返します

int main(){int retval = 0;

ベクトルcol(3); col [0] = 10。 col [1] = 20。 col [2] = 30。

それぞれ(const int)

cout << "retval:" << retval << endl; }


0


他のほとんどすべてのアルゴリズムをfor_each()に優先させる

2つの理由があります。

  1. for_eachは非常に一般的なもので、実際に行われていることについては何も言っていません。シーケンス内のすべての項目に対して何かを行っているということです。

  2. より特殊化されたアルゴリズムは、より単純で直接的なものになるでしょう。

以前の回答の例を考えてみましょう。

void print(int v){std :: cout << v << std :: endl; }
// ...
std :: for_each(array.begin()、array.end()、print); // STLを使用
代わりにstd

copyを使うと、全部が次のようになります。

std

copy(array.begin()、array.end()、std :: ostream_iterator(std :: cout、 "\ n"));


0


"struct functor {void operator()(Foo

std :: for_each(someVariable.begin()、someVariable.end()、functor()); "

私はこれらのようなアプローチはしばしば単純な問題のために不必要にバロック的だと思います。

i = 1を実行し、Nを呼び出す(X(i)、Y(i))を呼び出します。wo(Z(i))を呼び出します。

たとえ40歳であっても(明らかにCではなく)明らかに完全です。

コンテナーが常にベクトル(STL名)である場合は、インデックスで問題がないこと、およびそのインデックスを整数で呼び出すことで問題がないことがわかります。

実際には、多くの場合、同じサイズの複数のコンテナーを同時に反復処理し、それぞれからデータムをはがして、それらの多くで何かを実行する必要があります。 そのような状況で、特に、なぜインデックスを使わないのですか?

上記のSSSのポイント#2と#3に関しては、複雑なケースでもそうなる可能性があると思いますが、1 …​ Nを繰り返すことは他のものと同じくらい単純で明確であることがよくあります。

ホワイトボードでアルゴリズムを説明しなければならない場合、 'i’を使用して、または使用せずに、より早くそれを行うことができますか? あなたのミートスペースの説明がインデックスでより明確であれば、それをコードスペースで使用してください。

難しい目標のために重いCの火力を節約してください。