Apakah ada perbedaan dalam ++i
dan i++
dalam satu for
lingkaran? Apakah ini hanya masalah sintaksis?
Apakah ada perbedaan dalam ++i
dan i++
dalam satu for
lingkaran? Apakah ini hanya masalah sintaksis?
Jawaban:
++ dikenal sebagai postfix.
tambah 1 ke a, kembalikan nilai yang lama.
++ a dikenal sebagai awalan.
tambah 1 ke, mengembalikan nilai baru.
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++);
}
Keluaran:
1
2
3
4
0
1
2
3
foreach
dan while
loop tergantung pada tipe kenaikan mana yang Anda gunakan. Dengan untuk loop seperti di bawah ini tidak ada bedanya karena Anda tidak menggunakan nilai pengembalian 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
Jika nilai yang dievaluasi digunakan maka jenis kenaikan menjadi signifikan:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
Pre-increment ++ i menambah nilai i dan mengevaluasi ke nilai incremented yang baru.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
Post-increment i ++ menambah nilai i dan mengevaluasi ke nilai non-incremented yang asli.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
Di C ++, pre-increment biasanya lebih disukai di mana Anda bisa menggunakan keduanya.
Ini karena jika Anda menggunakan post-increment, itu dapat meminta kompiler harus membuat kode yang menciptakan variabel sementara tambahan. Ini karena nilai-nilai sebelumnya dan baru dari variabel yang ditingkatkan perlu disimpan di suatu tempat karena mereka mungkin diperlukan di tempat lain dalam ekspresi yang sedang dievaluasi.
Jadi, setidaknya di C ++, ada perbedaan kinerja yang memandu pilihan Anda untuk digunakan.
Ini terutama hanya masalah ketika variabel yang ditambahkan adalah tipe yang ditentukan pengguna dengan operator ++ yang ditimpa. Untuk tipe primitif (int, dll) tidak ada perbedaan kinerja. Tapi, ada baiknya tetap berpegang teguh pada operator pra-kenaikan sebagai pedoman kecuali jika operator pasca kenaikan pasti yang diperlukan.
Ada beberapa diskusi lagi di sini:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
Di C ++ jika Anda menggunakan STL, maka Anda mungkin menggunakan untuk loop dengan iterator. Ini sebagian besar memiliki operator ++ utama, jadi tetap berpegang pada pra-kenaikan adalah ide yang bagus. Kompiler menjadi lebih pintar sepanjang waktu, dan yang lebih baru mungkin dapat melakukan optimasi yang berarti tidak ada perbedaan kinerja - terutama jika tipe yang bertambah didefinisikan secara inline dalam file header (seperti implementasi STL yang sering) sehingga kompiler dapat melihat bagaimana metode ini diterapkan dan kemudian dapat mengetahui optimasi apa yang aman untuk dilakukan. Meski begitu, itu mungkin masih layak menempel pra-kenaikan karena loop dieksekusi berkali-kali dan ini berarti penalti kinerja kecil segera bisa diperkuat.
Dalam bahasa lain seperti C # di mana operator ++ tidak dapat kelebihan beban tidak ada perbedaan kinerja. Digunakan dalam loop untuk memajukan variabel loop, operator kenaikan pra dan pasca adalah setara.
Koreksi: overloading ++ dalam C # diperbolehkan. Tampaknya, dibandingkan dengan C ++, di c # Anda tidak dapat membebani versi pre dan post secara independen. Jadi, saya akan berasumsi bahwa jika hasil memanggil ++ di C # tidak ditugaskan ke variabel atau digunakan sebagai bagian dari ekspresi yang kompleks, maka kompiler akan mengurangi versi pra dan posting ++ ke kode yang berkinerja setara.
Dalam C # tidak ada perbedaan saat digunakan dalam for for loop .
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
menampilkan hal yang sama dengan
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Seperti yang telah ditunjukkan orang lain, ketika digunakan secara umum i ++ dan ++ i memiliki perbedaan yang halus namun signifikan:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++ membaca nilai i lalu menambahkannya.
++ i menambah nilai i lalu membacanya.
++i
dan i++
melakukan operasi yang sama dalam urutan yang sama: membuat salinan temp i
; menambah nilai temp untuk menghasilkan nilai baru (tidak untuk menimpa temp); simpan nilai baru di i
; sekarang jika ++i
hasilnya dikembalikan adalah nilai baru; jika i++
hasilnya dikembalikan adalah salinan temp. Jawaban lebih rinci di sini: stackoverflow.com/a/3346729/3330348
Pertanyaannya adalah:
Apakah ada perbedaan dalam ++ i dan i ++ di dalam for loop?
Jawabannya adalah: Tidak .
Mengapa masing-masing dan setiap jawaban lainnya harus masuk ke penjelasan terperinci tentang kenaikan sebelum dan sesudah ketika ini bahkan tidak ditanyakan?
Ini untuk-loop:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Akan menerjemahkan ke kode ini tanpa menggunakan loop:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
Sekarang apakah itu penting jika Anda memasukkan i++
atau ++i
sebagai kenaikan di sini? Tidak, itu tidak karena nilai pengembalian operasi kenaikan tidak signifikan. i
akan bertambah setelah eksekusi kode yang ada di dalam for loop body.
Karena Anda bertanya tentang perbedaan dalam satu lingkaran, saya kira maksud Anda
for(int i=0; i<10; i++)
...;
Dalam hal ini, Anda tidak memiliki perbedaan dalam sebagian besar bahasa: Loop berperilaku sama terlepas dari apakah Anda menulis i++
dan ++i
. Dalam C ++, Anda dapat menulis versi Anda sendiri dari operator ++, dan Anda dapat mendefinisikan arti yang terpisah untuk mereka, jika itu i
adalah tipe yang ditentukan pengguna (kelas Anda sendiri, misalnya).
Alasan mengapa itu tidak masalah di atas adalah karena Anda tidak menggunakan nilai i++
. Hal lain adalah ketika Anda melakukannya
for(int i=0, a = 0; i<10; a = i++)
...;
Sekarang, ada adalah perbedaan, karena sebagai orang lain menunjukkan, i++
berarti kenaikan, namun mengevaluasi nilai sebelumnya , tapi ++i
berarti kenaikan, namun mengevaluasii
(sehingga akan mengevaluasi ke nilai baru). Dalam kasus di atas, a
ditetapkan nilai sebelumnya dari i, sementara i bertambah.
Seperti yang ditunjukkan kode ini (lihat MSIL yang tidak jelas dalam komentar), kompiler C # 3 tidak membuat perbedaan antara i ++ dan ++ i dalam for for loop. Jika nilai i ++ atau ++ i diambil, pasti akan ada perbedaan (ini dikompilasi dalam 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++;
}
}
}
}
Satu (++ i) adalah preincrement, satu (i ++) adalah postincrement. Perbedaannya adalah dalam nilai apa yang segera dikembalikan dari ekspresi.
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
Sunting: Woops, sepenuhnya mengabaikan sisi loop hal. Tidak ada perbedaan nyata untuk loop ketika itu adalah bagian 'langkah' (untuk (...; ...;)), tetapi ini dapat ikut bermain dalam kasus lain.
Tidak ada perbedaan jika Anda tidak menggunakan nilai setelah kenaikan dalam loop.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Kedua loop akan mencetak 0123.
Tetapi perbedaannya datang ketika Anda menggunakan nilai setelah kenaikan / penurunan di loop Anda seperti di bawah ini:
Pra Pertambahan Loop:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Output: 0 0 1 1 2 2 3 3
Post Increment Loop:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Output: 0 0 1 0 2 1 3 2
Saya harap perbedaannya jelas dengan membandingkan output. Poin yang perlu diperhatikan di sini adalah kenaikan / penurunan selalu dilakukan pada akhir for loop dan karenanya hasilnya dapat dijelaskan.
Berikut adalah Java-Sample dan Byte-Code, post- dan preIncrement tidak menunjukkan perbedaan dalam 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;
}
}
}
Dan sekarang untuk byte-code (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
}
Ya ada. Perbedaannya terletak pada nilai balik. Nilai kembali "++ i" akan menjadi nilai setelah menambahkan i. Kembalinya "i ++" akan menjadi nilai sebelum bertambah. Ini berarti kode yang terlihat seperti berikut:
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.
Oleh karena itu, a akan menjadi 2, dan b dan c masing-masing akan menjadi 1.
Saya bisa menulis ulang kode seperti ini:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
Tidak ada perbedaan aktual dalam kedua kasus ' i
' akan bertambah 1.
Tetapi ada perbedaan ketika Anda menggunakannya dalam ekspresi, misalnya:
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
Ada lebih banyak ke ++ i dan i ++ daripada loop dan perbedaan kinerja. ++ i mengembalikan nilai-l dan i ++ mengembalikan nilai-r. Berdasarkan hal ini, ada banyak hal yang dapat Anda lakukan untuk (++ i) tetapi tidak untuk (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;
}
Ini mengejutkan pikiran saya mengapa begitu orang dapat menulis ekspresi kenaikan di-loop sebagai i ++.
Dalam for-loop, ketika komponen ke-3 adalah pernyataan kenaikan sederhana, seperti pada
for (i=0; i<x; i++)
atau
for (i=0; i<x; ++i)
tidak ada perbedaan dalam eksekusi yang dihasilkan.
Seperti yang dikatakan @Jon B , tidak ada perbedaan dalam for for loop.
Tetapi dalam satu while
atau do...while
loop, Anda bisa menemukan beberapa perbedaan jika Anda membuat perbandingan dengan ++i
ataui++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
Dalam javascript karena i ++ berikut mungkin lebih baik digunakan:
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.
Sementara array (saya pikir semua) dan beberapa fungsi dan panggilan lainnya menggunakan 0 sebagai titik awal Anda harus mengatur i ke -1 untuk membuat loop bekerja dengan array saat menggunakan ++ i .
Saat menggunakan i ++ nilai berikut akan menggunakan nilai yang meningkat. Anda bisa mengatakan i ++ adalah cara manusia menghitung, karena Anda bisa mulai dengan 0 .
Untuk memahami apa yang dilakukan loop FOR
Gambar di atas menunjukkan bahwa FOR dapat dikonversi ke WHILE , karena mereka akhirnya memiliki kode rakitan yang sama (setidaknya dalam gcc). Jadi kita dapat memecah FOR menjadi beberapa bagian, untuk melakukan dan apa yang dilakukannya.
for (i = 0; i < 5; ++i) {
DoSomethingA();
DoSomethingB();
}
sama dengan versi WHILE
i = 0; //first argument (a statement) of for
while (i < 5 /*second argument (a condition) of for*/) {
DoSomethingA();
DoSomethingB();
++i; //third argument (another statement) of for
}
Ini berarti bahwa Anda dapat menggunakan FOR sebagai versi sederhana WHILE :
Argumen pertama FOR (int i) dieksekusi, di luar, sebelum loop.
Argumen ketiga FOR (i ++ atau ++ i) dieksekusi, di dalam, di baris terakhir dari loop.
TL: DR: tidak peduli apakah
i++
atau++i
, kita tahu bahwa ketika mereka berdiri sendiri, mereka tidak membuat perbedaan selain +1 pada diri mereka sendiri.Di sekolah, mereka biasanya mengajarkan cara i ++, tetapi ada juga banyak orang lebih suka cara ++ i karena beberapa alasan .
CATATAN: Di masa lalu, i ++ memiliki dampak yang sangat kecil pada kinerja, karena tidak hanya ditambah satu dengan sendirinya, tetapi juga menyimpan nilai asli dalam register. Tetapi untuk saat ini, tidak ada bedanya karena kompiler membuat bagian plus satu sama.
Mungkin ada perbedaan untuk loop. Ini adalah aplikasi praktis pasca / kenaikan.
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
Sementara yang pertama dihitung menjadi 11 dan loop 11 kali, yang kedua tidak.
Sebagian besar ini agak digunakan dalam waktu yang sederhana (x--> 0); - - Loop untuk beralih misalnya semua elemen array (kecuali foreach-constructs di sini).
Mereka berdua menambah jumlahnya. ++i
setara dengan i = i + 1
.
i++
dan ++i
sangat mirip tetapi tidak persis sama. Keduanya menambah angka, tetapi ++i
menambah angka sebelum ekspresi saat ini dievaluasi, sedangkan i++
menambah angka setelah ekspresi dievaluasi.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Periksa tautan ini .
Ya, ada perbedaan antara ++i
dan i++
dalam satu for
lingkaran, meskipun dalam kasus penggunaan yang tidak biasa; ketika variabel loop dengan operator kenaikan / penurunan digunakan dalam for for atau dalam ekspresi tes loop , atau dengan salah satu variabel loop . Tidak, itu bukan hanya masalah sintaksis.
Seperti i
dalam kode berarti mengevaluasi ekspresi i
dan operator tidak berarti evaluasi tetapi hanya operasi;
++i
berarti nilai selisih i
1 dan kemudian dievaluasi i
,i++
berarti mengevaluasi i
dan kemudian nilai kenaikan i
sebesar 1.Jadi, apa yang diperoleh dari masing-masing dua ekspresi berbeda karena apa yang dievaluasi berbeda di masing-masing. Semua sama untuk --i
dani--
Sebagai contoh;
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
Dalam kasus penggunaan yang tidak biasa, namun contoh berikut kedengarannya bermanfaat atau tidak, itu menunjukkan perbedaan
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)
}
Untuk i
tipe yang ditentukan pengguna, operator ini bisa (tetapi tidak boleh ) memiliki semantik yang berbeda dalam konteks indeks loop, dan ini dapat (tetapi tidak seharusnya) mempengaruhi perilaku loop yang dijelaskan.
Juga, di c++
dalamnya umumnya paling aman untuk menggunakan formulir pra-kenaikan ( ++i
) karena lebih mudah dioptimalkan. (Scott Langham mengalahkan saya untuk berita gembira ini . Kutukan Anda, Scott)
Saya tidak tahu bahasa lain tetapi di Java ++ i adalah peningkatan awalan yang berarti: meningkatkan i dengan 1 dan kemudian menggunakan nilai baru dari i dalam ekspresi di mana saya berada, dan i ++ adalah peningkatan postfix yang berarti berikut : gunakan nilai i saat ini dalam ekspresi dan kemudian tambahkan dengan 1. Contoh:
public static void main(String [] args){
int a = 3;
int b = 5;
System.out.println(++a);
System.out.println(b++);
System.out.println(b);
} dan hasilnya adalah: