++i
C では、との使用の違いは何ですか? また、ループi++
のインクリメント ブロックでどちらを使用する必要がありますか?for
22 に答える
++i
の値をインクリメントし、インクリメントされた値をi
返します。i = 1; j = ++i; (i is 2, j is 2)
i++
の値をインクリメントしますが、インクリメントされる前に保持されi
ていた元の値を返します。i
i = 1; j = i++; (i is 2, j is 1)
for
ループの場合、どちらでも機能します。++i
おそらくそれがK&Rで使用されているためです。
いずれにせよ、ガイドライン「prefer ++i
over i++
」に従えば、間違いはありません。
との効率に関するコメントがいくつかあり++i
ますi++
。学生プロジェクト以外のコンパイラでは、パフォーマンスの違いはありません。これは、生成されたコードを確認することで確認できます。コードは同じです。
効率の質問は興味深いです... これが私の答えの試みです: C の i++ と ++i の間にパフォーマンスの違いはありますか?
@OnFreundが指摘しているようoperator++()
に、関数であり、コンパイラは一時オブジェクトの作成を最適化して中間値を保持することを知ることができないため、C++ オブジェクトの場合は異なります。
i++はPostIncrementと呼ばれ、++iはPreIncrementと呼ばれます。
i++
i++
i
操作が終了した後、の値を1インクリメントするため、ポストインクリメントです。
次の例を見てみましょう。
int i = 1, j;
j = i++;
ここでは、j = 1
butの値i = 2
。ここでは、の値が最初i
に割り当てられ、j
次にi
増分されます。
++i
++i
i
は、操作の前にの値を1インクリメントするため、事前インクリメントです。j = i;
の後に実行されることを意味しi++
ます。
次の例を見てみましょう。
int i = 1, j;
j = ++i;
ここでは、j = 2
butの値i = 2
。ここで、の値は。の 増分後にi
に割り当てられます。同様に、の前に実行されます。j
i
i
++i
j=i;
forループのインクリメントブロックで使用する必要がある質問について はどうでしょうか。答えは、あなたは誰でも使うことができるということです..関係ありません。それはあなたのforループを同じ番号で実行します。時の。
for(i=0; i<5; i++)
printf("%d ",i);
と
for(i=0; i<5; ++i)
printf("%d ",i);
両方のループで同じ出力が生成されます。すなわち0 1 2 3 4
。
どこで使用するかだけが重要です。
for(i = 0; i<5;)
printf("%d ",++i);
この場合、出力はになります1 2 3 4 5
。
i++
: このシナリオでは、最初に値が割り当てられ、次にインクリメントが発生します。
++i
: このシナリオでは、最初にインクリメントが行われ、次に値が割り当てられます
以下は画像のビジュアライゼーションです。これは、同じことを示す素晴らしい実用的なビデオです。
++i
値をインクリメントしてから返します。
i++
値を返し、インクリメントします。
微妙な違いです。
for ループの場合は++i
、わずかに高速な を使用します。i++
ただ捨てられる余分なコピーを作成します。
どちらが速いかという「効率」(実際の速度)は気にしないでください。最近では、これらのことを処理するコンパイラがあります。意図をより明確に示すものに基づいて、使用するのが理にかなっている方を使用してください。
その理由は、増分される前にiの値のローカルコピーを必要とする場合よりもわずかに速くなる可能性がありますが、決してそう++i
ではありません。場合によっては、可能であれば一部のコンパイラが最適化することもありますが、常に可能であるとは限りません。また、すべてのコンパイラがこれを行うわけではありません。i++
i++
++i
コンパイラの最適化にあまり依存しないようにしているので、Ryan Foxのアドバイスに従います。両方を使用できる場合は、を使用します++i
。
ループ内でどちらを使用しても、効果的な結果は同じです。つまり、ループは両方のインスタンスでまったく同じことを行います。
効率の点では、++i よりも i++ を選択すると、ペナルティが発生する可能性があります。言語仕様に関しては、ポストインクリメント演算子を使用すると、演算子が作用する値の余分なコピーが作成されます。これは、余分な操作の原因になる可能性があります。
ただし、前述のロジックに関する 2 つの主な問題を考慮する必要があります。
最新のコンパイラは素晴らしいです。すべての優れたコンパイラは、for ループで整数のインクリメントが発生していることを認識するほど賢く、両方のメソッドを同じ効率的なコードに最適化します。プリインクリメントよりもポストインクリメントを使用すると、実際にプログラムの実行時間が遅くなる場合は、ひどいコンパイラを使用しています。
操作時間の複雑さに関しては、2 つの方法は (コピーが実際に実行されている場合でも) 同等です。ループ内で実行される命令の数は、インクリメント操作の操作の数を大幅に支配する必要があります。したがって、かなりのサイズのループでは、インクリメント メソッドのペナルティは、ループ本体の実行によって大幅に影が薄くなります。言い換えれば、インクリメントよりもループ内のコードの最適化について心配する方がはるかに優れています。
私の意見では、問題全体は単純にスタイルの好みに帰着します。プレインクリメントの方が読みやすいと思われる場合は、それを使用してください。個人的にはポストインクリメントの方が好きなのですが、最適化を知らずに教わったからかもしれません。
これは時期尚早の最適化の典型的な例であり、このような問題は、設計における深刻な問題から私たちの注意をそらす可能性があります。ただし、「ベスト プラクティス」の使用法やコンセンサスに統一性がないため、これは依然として良い質問です。
++i
(前置操作): 値をインクリメントしてから割り当てます
(例): int i = 5
、int b = ++i
この場合、6 が最初に b に割り当てられ、次に 7 にインクリメントされます。
i++
(後置操作): 値を割り当ててからインクリメントします
(例): int i = 5
、int b = i++
この場合、5 が最初に b に割り当てられ、次に 6 にインクリメントされます。
for ループの場合:通常はfor ループでインクリメントする前i++
の開始値を使用するため、主に使用されます。i
ただし、プログラムのロジックによっては異なる場合があります。
まもなく:
++i
i++
関数に記述していない場合も同様に機能します。のようなものを使用するとfunction(i++)
、function(++i)
違いがわかります。
function(++i)
最初に i を 1 インクリメントし、その後これi
を新しい値で関数に入れます。
function(i++)
i
1インクリメントした後、最初に関数に入れると言いますi
。
int i=4;
printf("%d\n",pow(++i,2));//it prints 25 and i is 5 now
i=4;
printf("%d",pow(i++,2));//it prints 16 i is 5 now
これでセマンティクスの違いが理解できたと思います (正直なところ、本や Web チュートリアルなどを読むのではなく、スタック オーバーフローについて「演算子 X の意味は何か」という質問をする人がいるのが不思議です。
とにかく、どちらを使用するかについては、パフォーマンスの問題は無視してください。パフォーマンスの問題は、C++ でも重要ではありません。これは、どちらを使用するかを決定する際に使用する必要がある原則です。
あなたがコードで何を意味するかを言ってください。
ステートメントで value-before-increment が必要ない場合は、その形式の演算子を使用しないでください。これは些細な問題ですが、一方のバージョンを禁止してもう一方のバージョンを完全に禁止するスタイル ガイド (骨の折れるスタイル ガイドとも呼ばれます) を使用している場合を除き、実行しようとしていることを最も正確に表現する形式を使用する必要があります。
QED、プレインクリメント バージョンを使用します。
for (int i = 0; i != X; ++i) ...
プリクリメントとは、同じ行でインクリメントすることを意味します。ポストインクリメントとは、行の実行後にインクリメントすることを意味します。
int j=0;
System.out.println(j); //0
System.out.println(j++); //0. post-increment. It means after this line executes j increments.
int k=0;
System.out.println(k); //0
System.out.println(++k); //1. pre increment. It means it increments first and then the line executes
OR、AND 演算子を使用すると、さらに興味深いものになります。
int m=0;
if((m == 0 || m++ == 0) && (m++ == 1)) { //false
/* in OR condition if first line is already true then compiler doesn't check the rest. It is technique of compiler optimization */
System.out.println("post-increment "+m);
}
int n=0;
if((n == 0 || n++ == 0) && (++n == 1)) { //true
System.out.println("pre-increment "+n); //1
}
配列内
System.out.println("In Array");
int[] a = { 55, 11, 15, 20, 25 } ;
int ii, jj, kk = 1, mm;
ii = ++a[1]; // ii = 12. a[1] = a[1] + 1
System.out.println(a[1]); //12
jj = a[1]++; //12
System.out.println(a[1]); //a[1] = 13
mm = a[1];//13
System.out.printf ( "\n%d %d %d\n", ii, jj, mm ) ; //12, 12, 13
for (int val: a) {
System.out.print(" " +val); //55, 13, 15, 20, 25
}
C++ では、ポインター変数のポスト/プリインクリメント
#include <iostream>
using namespace std;
int main() {
int x=10;
int* p = &x;
std::cout<<"address = "<<p<<"\n"; //prints address of x
std::cout<<"address = "<<p<<"\n"; //prints (address of x) + sizeof(int)
std::cout<<"address = "<<&x<<"\n"; //prints address of x
std::cout<<"address = "<<++&x<<"\n"; //error. reference can't re-assign because it is fixed (immutable)
}
a=i++ は、a に現在の i 値が含まれていることを意味します a=++i は、a にインクリメントされた i 値が含まれていることを意味します
違いを理解するための例を次に示します
int i=10;
printf("%d %d",i++,++i);
出力: 10 12/11 11
(関数への引数の評価の順序に応じて、printf
コンパイラとアーキテクチャによって異なります)
説明:
i++
->i
が出力され、インクリメントされます。(10を出力しますi
が、11 になります)
++i
->i
値がインクリメントされ、値が出力されます。(出力は 12 で、値i
も 12 です)