for
ループ内の++i
とi++
に違いはありますか?それは単なるシンタックスなのでしょうか。
++はpostfixとして知られています。
aに1を加えて、古い値を返します。
++ aは接頭辞として知られています。
aに1を加えて、新しい値を返します。
C#:
string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
Console.WriteLine(++i);
}
Console.WriteLine("");
i = 0;
foreach (string item in items)
{
Console.WriteLine(i++);
}
出力:
1
2
3
4
0
1
2
3
foreach
およびwhile
ループは、使用する増分タイプによって異なります。以下のようなforループでは、iの戻り値を使っていないので違いはありません。
for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }
0 1 2 3 4
0 1 2 3 4
評価された値が使用される場合、増分のタイプは重要になります。
int n = 0;
for (int i = 0; n < 5; n = i++) { }
++ iの前増分++は、iの値を増分し、新しい増分値に評価します。
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
ポストインクリメントi ++は、iの値をインクリメントし、元のインクリメントされていない値に評価します。
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
C++では、プリインクリメントは通常、どちらを使用できる場合でも優先されます。
これは、ポストインクリメントを使用すると、コンパイラが余分な一時変数を作成するコードを生成しなければならなくなる可能性があるためです。これは、インクリメントされる変数の以前の値と新しい値の両方が、評価される式の他の場所で必要になる可能性があるため、どこかに保持する必要があるためです。
したがって、少なくともC++では、どちらを使用するかの選択を左右する、パフォーマンスの違いがある可能性があります。
これは主に、増分される変数が、オーバーライドされた++演算子を持つユーザー定義型である場合にのみ問題になります。プリミティブ型(intなど)の場合、パフォーマンス上の違いはありません。しかし、ポストインクリメント演算子が間違いなく必要なものでない限り、ガイドラインとしてプレインクリメント演算子に固執する価値があります。
ここでもう少し議論があります:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
C++でSTLを使用している場合は、forループをイテレータと共に使用している可能性があります。これらは主にオーバーライドされた++演算子を持っているので、プリインクリメントに固執することは良い考えです。ただし、コンパイラは常に賢くなり、新しいものではパフォーマンスの違いがないことを意味する最適化を実行できる可能性があります。特に、STL実装でよく見られるように(インクリメントされる型がヘッダファイルでインラインで定義される場合)メソッドが実装され、どの最適化を実行しても安全かを知ることができます。そうであっても、ループは何度も実行されるのでプリインクリメントに固執する価値があるかもしれません。これはすぐにわずかなパフォーマンスペナルティが増幅される可能性があることを意味します。
++演算子をオーバーロードできないC#などの他の言語では、パフォーマンスに違いはありません。ループ変数を進めるためにループ内で使用される、前後のインクリメント演算子は同等です。
訂正:C#での++のオーバーロードは許可されています。 C#と比較して、C#ではプレバージョンとポストバージョンを別々にオーバーロードすることはできません。そのため、C#で++を呼び出した結果が変数に割り当てられていない場合、または複雑な式の一部として使用されていない場合、コンパイラは前後のバージョンの++を同等に機能するコードに減らします。
C#では違いはありませんforループで使用される場合。
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
と同じものを出力する
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
他の人が指摘したように、一般にi ++と++ iを使用すると、微妙ではあるが大きな違いがあります。
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++はiの値を読み取り、次にそれを増分します。
++ iはiの値をインクリメントしてから読み込みます。
質問は:
Forループで、++ iとi ++に違いはありますか?
答えは次のとおりです。いいえ。
これが求められていないのに、なぜそれぞれの答えが前後のインクリメントについての詳細な説明に入らなければならないのでしょうか。
このforループ
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
ループを使用せずにこのコードに変換します。
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
ここでi++
または++i
を増分としてここに入れても問題ありませんか。 いいえ、そうではありませんインクリメント操作の戻り値は重要ではないため。 i
は、forループ本体内にあるコードの実行後に増分されます。
あなたはループの違いについて尋ねるので、私はあなたが意味すると思います
for(int i=0; i<10; i++)
...;
その場合、ほとんどの言語で違いはありません。ループは、i++
と++i
のどちらを書いても同じように動作します。 C++では、独自のバージョンの++演算子を書くことができます。また、i
がユーザー定義型(たとえば、独自のクラス)の場合は、それらに別々の意味を定義することができます。
上記のことが問題にならないのは、i++
の値を使わないからです。別のことはあなたがするときです
for(int i=0, a = 0; i<10; a = i++)
...;
さて、is違いがあります。他の人が指摘するように、i++
はインクリメント、しかし前の値に評価する、しかし++i
はインクリメント、しかし評価するにはi
(したがって、新しい値に評価されます)。上記の場合、a
には前のiの値が割り当てられ、iはインクリメントされます。
このコードが示すように(コメント内の分解されたMSILを参照)、C#3コンパイラはforループ内でi ++と++ iを区別しません。 i ++または++ iの値が採用されている場合は、間違いなく違いがあります(これはVisutal Studio 2008/Release Buildでコンパイルされています)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PreOrPostIncrement
{
class Program
{
static int SomethingToIncrement;
static void Main(string[] args)
{
PreIncrement(1000);
PostIncrement(1000);
Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
}
static void PreIncrement(int count)
{
/*
.method private hidebysig static void PreIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PreIncrement
*/
for (int i = 0; i < count; ++i)
{
++SomethingToIncrement;
}
}
static void PostIncrement(int count)
{
/*
.method private hidebysig static void PostIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PostIncrement
*/
for (int i = 0; i < count; i++)
{
SomethingToIncrement++;
}
}
}
}
1つ(++ i)は前インクリメント、1つ(i ++)は後インクリメントです。違いは、式からすぐに返される値にあります。
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
編集:ウープ、物事のループ側を完全に無視した。 forステップが 'step'の部分(for(...; ...;))の場合、forループに実際の違いはありませんが、他の場合には効果があります。
これがJavaサンプルであり、Byte-Code、post-and preIncrementはBytecodeに違いはありません。
public class PreOrPostIncrement {
static int somethingToIncrement = 0;
public static void main(String[] args) {
final int rounds = 1000;
postIncrement(rounds);
preIncrement(rounds);
}
private static void postIncrement(final int rounds) {
for (int i = 0; i < rounds; i++) {
somethingToIncrement++;
}
}
private static void preIncrement(final int rounds) {
for (int i = 0; i < rounds; ++i) {
++somethingToIncrement;
}
}
}
そして今、バイトコード(javap -private -c PreOrPostIncrement)の場合:
public class PreOrPostIncrement extends Java.lang.Object{
static int somethingToIncrement;
static {};
Code:
0: iconst_0
1: putstatic #10; //Field somethingToIncrement:I
4: return
public PreOrPostIncrement();
Code:
0: aload_0
1: invokespecial #15; //Method Java/lang/Object."<init>":()V
4: return
public static void main(Java.lang.String[]);
Code:
0: sipush 1000
3: istore_1
4: sipush 1000
7: invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return
private static void postIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
private static void preIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
}
ループ内でインクリメント後の値を使用していないのであれば、違いはありません。
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
両方のループが0123を印刷します。
しかし、以下のように、ループ内でインクリメント/デクリメント後の値を使用すると違いが出ます。
プレインクリメントループ:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
出力:0 0 1 1 2 2 3 3
インクリメント後のループ
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
出力:0 0 1 0 2 1 3 2
出力を比較して、違いが明らかになることを願っています。ここで注意しなければならないのは、インクリメント/デクリメントは常にforループの最後で行われるため、結果を説明できることです。
はいあります。違いは戻り値にあります。 "++ i"の戻り値は、after iを増分した値になります。 "i ++"の戻り値は、前増加する値になります。これは、次のようなコードです。
int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.
したがって、aは2、bとcはそれぞれ1になります。
私はこのようにコードを書き直すことができます:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
どちらの場合も実際の違いはありません。 'i
'は1ずつ増加します。
しかし、式の中でそれを使うと違いがあります。例えば:
int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3
++ iとi ++には、ループとパフォーマンスの違い以上のものがあります。 ++ iはl値を返し、i ++はr値を返します。これに基づいて、(++ i)にできることはたくさんありますが、(i ++)にはできません。
1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:
T& operator ++ ( )
{
// logical increment
return *this;
}
const T operator ++ ( int )
{
T temp( *this );
++*this;
return temp;
}
それが私の頭を悩ませます。なぜなら、人々はforループでi ++としてインクリメント式を書くかもしれません。
Forループで、3番目の要素が次のように単純なincrementステートメントの場合
for (i=0; i<x; i++)
または
for (i=0; i<x; ++i)
実行結果に違いはありません。
Javascriptでは、次のような理由からi ++を使うのが良いかもしれません。
var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.
配列(私はすべてだと思います)および他のいくつかの関数と呼び出しは開始点として0を使用しますが、++ iを使用するときループを配列で動作させるにはiを-1に設定する必要があります。
i ++を使用すると、次の値は増加した値を使用します。あなたはi ++が人間の数え方であると言えるでしょう、なぜならあなたはで始めることができるからです。
@ Jon B の通り、forループに違いはありません。
しかしwhile
またはdo...while
ループでは、++i
またはi++
と比較している場合は、いくつかの違いがあります。
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
ループには違いがあります。これはpost/pre-incrementの実用的なアプリケーションです。
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
最初のものは11まで数え、11回ループしますが、2番目はしません。
ほとんどの場合、これは単純なwhile(x--> 0)で使用されます。 - - たとえば、配列のすべての要素を繰り返すためのループ(ここではforeach-constructを除く)。
両方とも数を増やします。 ++i
はi = i + 1
と同等です。
i++
と++i
はよく似ていますが、まったく同じではありません。両方とも数値をインクリメントしますが、++i
は現在の式が評価される前に数値をインクリメントしますが、i++
は式が評価された後に数値をインクリメントします。
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
--- このリンク を確認してください。
はい、for
ループでは++i
とi++
の間に違いがあります。インクリメント/デクリメント演算子を使用したループ変数が使用されている場合forブロック内またはループテスト式内またはループ変数の1つを使用 。いいえ、それは単なる構文上の問題ではありません。
コード内のi
は式i
を評価することを意味し、演算子は評価を意味するのではなく単なる操作を意味します。
++i
はi
の値を1増やし、後でi
を評価することを意味します。i++
は、i
を評価し、後でi
の値を1増やします。したがって、評価されるものがそれぞれ異なるため、2つの式それぞれから得られるものは異なります。 --i
とi--
についても同じ
例えば;
let i = 0
i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1
0
i
1
++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2
2
i
2
珍しい使用例では、次の例は役に立つように聞こえるかどうかは関係ありませんが、違いを示しています
for(i=0, j=i; i<10; j=++i){
console.log(j, i)
}
for(i=0, j=i; i<10; j=i++){
console.log(j, i)
}