3

与えられた

std::vector<CMyClass> objects;
CMyClass list[MAX_OBJECT_COUNT];

これを行うのは賢明ですか?

for(unsigned int i = 0; i < objects.size(); list[i] = objects.at(i++));

または、ループをこれに拡張する必要がありますか?

for(unsigned int i = 0; i < objects.size(); i++)
{
  list[i] = objects.at(i);
}
4

4 に答える 4

11

前者は未定義の動作です。list[i]への関数呼び出しの前または後に (割り当ての左辺値を提供するために) が評価されるかどうかは指定されていませんobjects.at

したがって、式のさまざまな部分の正当な順序付けがあり、シーケンス ポイントを介さずにiアクセス ( list[i]) され、個別に変更 ( ) されます。i++

これはまさに、C++ 標準における未定義の動作の条件です。そのような正当な順序が存在するかどうかです。IIRC の C 標準では、表現が少し異なりますが、効果は同じです。

疑問がある場合は、インクリメント演算子を使用する式を記述しないでください。また、式の他の場所でも同じ値を使用します。コンマ演算子 ( は問題ありませんi++, i++) と条件演算子 (i ? i++ : i--は問題ありません) を使用して実行できます。これらにはシーケンス ポイントが含まれているためですが、その価値はほとんどありません。同様に、そしてそのようなもの||は完全に信じられないわけではありません。それ以外の使用法であり、十分に長い間それを見つめていれば、通常、物事を台無しにする評価の順序を考え出すことができます。&&p != end_p && *(p++) = something;

それは、複雑なfor式とfor空の本体を持つループの理解の容易さは別としてです。

于 2010-03-29T14:26:26.913 に答える
6

判断に迷う場合は、わかりやすい形式を優先してください (ループを展開します)。

list[i] = objects.at(i++)(そして、未定義の動作につながると思います。)

于 2010-03-29T14:23:24.500 に答える
1

すでに述べたように、使用されているのと同じ式で変数をポストインクリメントすると、未定義の動作が発生します。ただし、コンパクトな形式を維持したい場合は、シーケンスポイントを導入して、

for(unsigned int i = 0; i < objects.size(); list[i] = objects.at(i), i++);
于 2010-03-29T14:33:28.590 に答える
1

iと同じ式での参照は、i++おそらく未定義の動作です。しかし、コンテナを使用しているように見えるので、書いてもらえますか...

list = objects;                               // if they're the same type
list.assign(objects.begin(), objects.end());  // if not
于 2010-03-29T14:27:41.630 に答える