2009-07-02 10 views
24

可能性の重複:
Is there a performance difference between i++ and ++i in C++?イテレータをインクリメントする:++ ++よりも効率的です++?

が、私はイテレータがのstd ::ベクトルをループするために使用されているプログラムを書いています。誰かが、forステートメントで++を実行すると、より効率的なコードにつながると私に言った。言い換えれば、彼らはそれを言っている:

for (vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); ++it) 

実行速く

for (vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); it++) 

よりも、この本当ですか?そうであれば、効率改善の理由は何ですか?すべての++/++は、イテレータをベクトルの次のアイテムに移動するのですか?

+7

参照してください:http://stackoverflow.com/questions/24901/ – Shog9

+2

正確な複製が、担当者のレースはとにかくです。 – macbirdie

+1

これはイテレータに関するものなので、答えが必要です。他の質問は全体的な違いについて質問するようです。私はそれらが関連する質問だと思いますが、正確な重複はありませんか? –

答えて

2

時にははい。いくつかは、最適化され、同じになるでしょう。 std :: vector <(および他のstd-iterators)では、ほとんど同じように最適化されます。

0

はい。私が覚えている限り、++ ++は一時的なオブジェクトを作成するので++よりも効率的ですが、++はそれよりも効率的です。

1

はい++ ++はオブジェクトのコピーを返してからインクリメントする必要があるため、より効率的です。

31

プリインクリメントが遅いのは、ポストインクリメントが古い値のコピーを返さなければならないためです。 GotW #2のように、 "プリインクリメントはポストインクリメントより効率的です。ポストインクリメントの場合、オブジェクトはインクリメントしてから、古い値を含む一時的な値を返さなければなりません。これはintのような組み込み関数に対しても当てはまります。

GotW #55が、それは前置インクリメントプラスいくつかのより多くの作業を行う必要があることを示してポストインクリメントの正規の形式を、提供:

T T::operator++(int) 
{ 
    T old(*this); // remember our original value 
    ++*this;  // always implement postincrement 
        // in terms of preincrement 
    return old;  // return our original value 
} 

他の人が指摘したように、いくつかのコンパイラは、いくつかのケースでこれを離れて最適化するために、それが可能です、戻り値を使用しない場合は、この最適化に頼らないことをお勧めします。また、パフォーマンスの違いは、単純なコピーコンストラクタを持つタイプでは非常に小さいと思われますが、プリインクリメントを使用することはC++の優れた習慣であると思います。

+2

ディーセント・コンパイラは、決して使用されない場合、古い値のコピーを最適化します。 – Novelocrat

+2

正確には、(a)標準はそれを必要とせず、(b)2つが同等に効率的なソースコードとコンパイラの組み合わせを作成するのはかなり容易であるため、プリインクリメントがポストインクリメントよりも効率的であると約束することはできません。 –

+0

しかし、あなたは、前もって増額したものが少なくとも後増量と同じくらい効率的であると考えることができます。それでは、それが他の点で同等であるとき、なぜそれをいつも使うのではないのですか? –

2

++が一時コピーを作成する可能性があります。

また、C++では、ポストインクリメント演算子がオーバーロードされている可能性があります。

これらの両方は、パフォーマンスとプリインクリメントを低下させる可能性があります。実際にはどちらも問題ではないでしょう。特に、一時的なコピーは、Forループの3番目の式に副作用がないので、ほとんどのコンパイラによって最適化されます。

6

ベクターに違いはありません。

一般に、++itは、it++(過負荷の場合は適切な実装を前提としています)よりも遅くなる可能性は非常に低く、ほんの高速かもしれません。その理由は、反復子クラス自体がすべて複雑な場合、it++itがインクリメントされる前に値を返さなければならないため、実装は一般的にコピーを作成するためです。

ベクトルイテレータは、おそらく「単なるポインタ」(最適化では、非デバッグビルド)であり、両方operator++ sがインライン化されます。戻り値は使用されないので、コピーは通常省略されます。だから違いはありません。私は++itと入力しているので、

と入力した方がいいですね。1)何らかのイテレータタイプのために何か変わるかもしれないし、そのタイプのために特別なことをしたくないのです。対照的に、「それを使用して、インクリメント」に、「それをインクリメント」:

2)個人的に私は接頭辞オペレーターがより明確に意図を表現すると思います。

  1. それは
  2. 増分は、それが
  3. 復帰は、元の(非増分)が

++、実行するののコピーを作成する:

+0

私には2番の数字は++よりも紛らわしいと言わなければなりませんでした。例えば、forループを見ると、(int i = 0; i <10; i ++)は、私が0に設定した整数を持っていることを示しています。私が10以下であればこれをやりたいと思っていて、ループが終わるたびに1ずつ増やしたいと思っています)。私は最初はとても混乱していました。私は思ったことを覚えています。なぜ、何かをやる前に繰り返したいのですが、どうしてあなたが望むものよりも1つ少なくするのではなく、 )。 – Josh

+0

@Josh:これは新参者のforループの最後の部分がいつ実行されるかについての完全な混乱の結果に過ぎません。もちろん、あなたはまだ0に初期化され、 '++ i'か' i ++ 'のどちらを書き込むかにかかわらず、最初の値は0、2番目の値は1などです。率直に言えば、「++ i」と書くことで、新人が後でなくすぐにその混乱を解消するように促し、何が入っていてもループの本体の後に*が実行されることを理解してから、 '++ i'の追加利点! –

+0

私は大学に行く前に、私は高校に戻って悪い先生にチョークする必要がありますね。彼らは+ +私はそれがループ内のものを評価する前にインクリメントすることを意味し、私は+ +ループ内のものの評価後に増加するだろうと言った。私が最初から正確に言われたなら、混乱は決して存在していなかったでしょう。 – Josh

2

それは++以下の動作を行います次の操作:

  1. インクリメントそれは++のコピーを作成するので、それは

それ

  • リターンは、「遅く」であると言うことができます。しかし、まともなコンパイラは、ほとんどの定義された型に対してこの違いを最適化します。いくつかのユーザー定義型では、より速くなります。

  • +0

    「ゆっくり」という意味ですか? – Gobe

    関連する問題