Katakanlah Anda memiliki for
loop berikut *:
for (int i = 0; i < 10; ++i) {
// ...
}
yang secara umum dapat juga ditulis sebagai:
for (int i = 0; i != 10; ++i) {
// ...
}
Hasil akhirnya sama, jadi apakah ada argumen nyata untuk menggunakan satu di atas yang lain? Secara pribadi saya menggunakan yang pertama kalau i
- kalau karena alasan tertentu rusak dan melewatkan nilai 10.
* Maafkan penggunaan angka ajaib, tapi itu hanya sebuah contoh.
int i = 10; while(i --> 0) { /* stuff */ }
while ((i--) > 0)
Jawaban:
Alasan untuk memilih satu atau yang lain adalah karena niat dan sebagai akibatnya, ini meningkatkan keterbacaan .
Maksud: loop harus berjalan selama
i
lebih kecil dari 10, tidak selamai
tidak sama dengan 10. Meskipun yang terakhir mungkin sama dalam kasus khusus ini, bukan itu yang Anda maksud, jadi seharusnya tidak ditulis seperti itu.Keterbacaan: hasil dari menuliskan apa yang Anda maksud adalah bahwa hal itu juga lebih mudah dipahami. Misalnya, jika Anda menggunakan
i != 10
, seseorang yang membaca kode mungkin bertanya-tanya apakah di dalam loop ada beberapa cara yangi
bisa menjadi lebih besar dari 10 dan bahwa loop harus berlanjut (btw: itu gaya buruk untuk mengacaukan iterator di tempat lain daripada di kepala yangfor
pernyataan-, tapi itu tidak berarti orang tidak melakukannya dan sebagai hasilnya pengelola berharap).sumber
i
"lebih kecil dari 10", itu harus berjalan selama (dalam hal ini) batas atas tidak tercapai. Ketika menggunakan alasan kisaran C ++ interval / iterator, itu jauh lebih logis untuk mengekspresikan hal ini!=
daripada<
.<
sebenarnya ungkapkan dengan tepat.for
loop. Menggunakan di<
sini akan konyol. Deckard juga tampaknya mengakui hal itu. Saya sangat setuju dengan komentarnya dalam menanggapi komentar saya.!=
The
<
Pola umumnya digunakan bahkan jika kenaikan terjadi tidak menjadi 1 persis.Hal ini memungkinkan satu cara umum untuk melakukan loop terlepas dari bagaimana itu sebenarnya dilakukan.
sumber
i
untuk dimodifikasi di dalam loop sepenuhnya dengan aman jika perlu.<
, seperti iterator atas suatu urutan, dan karenanya!=
akan menjadi satu cara umum untuk melakukan loop di C ++.<
polanya karena membutuhkan satu ketukan alih-alih dua dengan>
polanya, dan empat dengan!=
. Ini masalah efisiensi mirip OCD.Dalam C ++ rekomendasi oleh Scott Myers di More Effective C ++ (item 6) selalu menggunakan yang kedua kecuali Anda memiliki alasan untuk tidak melakukannya karena itu berarti Anda memiliki sintaks yang sama untuk indeks iterator dan integer sehingga Anda dapat bertukar mulus antara
int
dan iterator tanpa ada perubahan sintaksis.Dalam bahasa lain ini tidak berlaku jadi saya kira
<
mungkin lebih disukai karena poin Thorbjørn Ravn Andersen.Ngomong-ngomong, hari lain saya mendiskusikan hal ini dengan pengembang lain dan dia mengatakan alasan untuk memilih
<
lebih!=
adalah karenai
secara tidak sengaja akan bertambah lebih dari satu, dan itu mungkin menyebabkan kondisi istirahat tidak terpenuhi; itu IMO banyak omong kosong.sumber
<
untuk menjadi pemrograman yang lebih defensif daripada!=
itu ...<
lebih defensif dan kolega saya benci jika saya menulis!=
jadi saya tidak. Namun, ada kasus!=
di C ++ dan itulah yang saya presentasikan.i++
adalah ketika mengubah loop sementara menjadi loop untuk. Tidak yakin bahwa memiliki setengah jumlah iterasi lebih baik daripada loop tak terbatas (dekat); yang terakhir mungkin akan membuat bug lebih jelas.Menggunakan (i <10) menurut saya merupakan praktik yang lebih aman. Ini menangkap jumlah maksimum kasus berhenti potensial - semua yang lebih besar dari atau sama dengan 10. Bandingkan ini dengan kasus lainnya (i! = 10); hanya menangkap satu kemungkinan berhenti - ketika saya tepat 10.
Produk sampingannya adalah ini meningkatkan keterbacaan. Selain itu, jika kenaikannya menjadi sesuatu yang lain 1, itu dapat membantu meminimalkan kemungkinan masalah jika kita membuat kesalahan saat menulis kasus berhenti.
Mempertimbangkan:
Meskipun kedua kasus kemungkinan cacat / salah, yang kedua cenderung LEBIH salah karena tidak akan berhenti. Kasus pertama akan berhenti, dan ada kemungkinan lebih tinggi untuk berhenti di tempat yang tepat, meskipun 14 mungkin angka yang salah (15 mungkin akan lebih baik).
sumber
Inilah jawaban lain yang tampaknya belum ada yang muncul.
for
loop harus digunakan ketika Anda harus mengulangi urutan . Menggunakan!=
adalah metode yang paling ringkas menyatakan kondisi terminating untuk loop. Namun, menggunakan operator yang tidak terlalu membatasi adalah idiom pemrograman defensif yang sangat umum. Untuk bilangan bulat tidak masalah - itu hanya pilihan pribadi tanpa contoh yang lebih spesifik. Looping koleksi dengan iterator yang ingin Anda gunakan!=
untuk alasan yang telah dinyatakan orang lain. Jika Anda mempertimbangkan urutanfloat
ataudouble
, maka Anda ingin menghindari!=
di semua biaya.Apa yang ingin saya tunjukkan adalah yang
for
digunakan ketika Anda perlu mengulangi urutan. Urutan yang dihasilkan memiliki titik awal, interval, dan kondisi terminating. Ini secara ringkas ditentukan dalamfor
pernyataan. Jika Anda menemukan diri Anda sendiri (1) tidak termasuk bagian langkahfor
atau (2) menentukan sesuatu sepertitrue
kondisi penjaga, maka Anda tidak boleh menggunakanfor
loop!The
while
loop digunakan untuk melanjutkan proses sementara kondisi tertentu terpenuhi. Jika Anda tidak memproses urutan, maka Anda mungkin inginwhile
lingkaran sebagai gantinya. Argumen kondisi penjaga serupa di sini, tetapi keputusan antara awhile
danfor
loop harus sangat sadar. Thewhile
loop kurang dihargai di kalangan C ++ IMO.Jika Anda sedang memproses koleksi item (penggunaan yang sangat umum
for
-loop), maka Anda benar-benar harus menggunakan metode yang lebih khusus. Sayangnya,std::for_each
cukup menyakitkan di C ++ karena sejumlah alasan. Dalam banyak kasus memisahkan tubuh darifor
loop dalam fungsi yang berdiri bebas (sementara agak menyakitkan) menghasilkan solusi yang jauh lebih bersih. Ketika bekerja dengan koleksi, mempertimbangkanstd::for_each
,std::transform
ataustd::accumulate
. Implementasi banyak algoritma menjadi ringkas dan jernih ketika diekspresikan dengan cara ini. Belum lagi bahwa mengisolasi tubuh loop ke dalam fungsi / metode terpisah memaksa Anda untuk berkonsentrasi pada algoritma, persyaratan inputnya, dan hasil.Jika Anda menggunakan Java, Python, Ruby, atau bahkan C ++ 0x , maka Anda harus menggunakan koleksi yang tepat foreach lingkaran. Ketika kompiler C ++ mengimplementasikan fitur ini, sejumlah
for
loop akan hilang sebagaimana jenis diskusi ini.sumber
while
,for
, danforeach
(atau equivilant bahasa)while
loop digunakan untuk melanjutkan proses sampai kondisi tertentu tidak terpenuhi<
) atau operator bersikap lunak dalam nilai yang gagal (!=
).Menggunakan "kurang dari" adalah (biasanya) benar secara semantik, maksud Anda benar-benar menghitung sampai
i
tidak kurang dari 10, jadi "kurang dari" menyampaikan niat Anda dengan jelas. Menggunakan "tidak sama" jelas bekerja dalam kasus panggilan sebenarnya, tetapi menyampaikan makna yang sedikit berbeda. Dalam beberapa kasus ini mungkin yang Anda butuhkan tetapi dalam pengalaman saya ini tidak pernah terjadi. Jika Anda benar-benar memiliki kasus di manai
mungkin lebih atau kurang dari 10 tetapi Anda ingin tetap mengulang sampai sama dengan 10, maka kode itu benar-benar perlu dikomentari dengan sangat jelas, dan mungkin bisa lebih baik ditulis dengan beberapa konstruksi lain, seperti sebagaiwhile
loop mungkin.sumber
Salah satu alasan mengapa saya lebih menyukai
less than
anot equals
adalah untuk bertindak sebagai penjaga. Dalam beberapa keadaan terbatas (pemrograman buruk atau sanitasi)not equals
dapat dilewati sedangkanless than
masih akan berlaku.Berikut adalah satu contoh di mana kurangnya pemeriksaan sanitasi telah menyebabkan hasil yang aneh: http://www.michaeleisen.org/blog/?p=358
sumber
Berikut adalah salah satu alasan mengapa Anda lebih suka menggunakan
<
daripada!=
. Jika Anda menggunakan bahasa yang memiliki cakupan variabel global, apa yang terjadi jika kode lain dimodifikasii
? Jika Anda menggunakan<
daripada!=
, yang terburuk yang terjadi adalah bahwa iterasi selesai lebih cepat: mungkin beberapa peningkatan kode lainnya secarai
tidak sengaja, dan Anda melewatkan beberapa iterasi dalam for loop. Tetapi apa yang terjadi jika Anda mengulangi 0 hingga 10, dan loop mencapai 9, dan beberapa penambahan untaian yang ditulis buruki
karena beberapa alasan aneh. Kemudian loop Anda menyelesaikan iterasi dan kenaikani
sehingga nilainya sekarang 11. Karena loop telah melewati kondisi keluar (i
tidak pernah sama dengan 10) sekarang akan loop berulang.Itu tidak harus harus terutama jenis logika threading-dan-global-variabel yang menyebabkan ini. Mungkin saja Anda sedang menulis loop yang perlu mundur. Jika Anda bermutasi
i
di dalam loop dan Anda mengacaukan logika Anda, memilikinya sehingga memiliki batas atas daripada!=
kecil cenderung meninggalkan Anda dalam loop tak terbatas.sumber
Di dunia tertanam, terutama di lingkungan yang bising, Anda tidak dapat mengandalkan RAM yang seharusnya berlaku sebagaimana mestinya. Dalam kondisi bersyarat (untuk, sementara, jika) di mana Anda membandingkan menggunakan '==' atau '! =' Anda selalu menghadapi risiko variabel Anda melewatkan nilai penting yang mengakhiri loop - ini dapat memiliki konsekuensi yang berbahaya - Mars Lander konsekuensi tingkat. Menggunakan '<' atau '>' dalam kondisi tersebut memberikan tingkat keamanan ekstra untuk menangkap 'tidak dikenal yang tidak dikenal'.
Dalam contoh asli, jika secara
i
tidak sengaja terlempar ke nilai yang jauh lebih besar dari 10, perbandingan '<' akan menangkap kesalahan segera dan keluar dari loop, tetapi '! =' Akan terus menghitung sampaii
dibungkus melewati 0 dan kembali ke 10.sumber
for (i=4; i<length; i++) csum+=dat[i];
mana paket yang sah akan selalu memilikilength
setidaknya empat, tetapi orang mungkin menerima paket yang rusak. Jika jenis paket yang berbeda memiliki persyaratan panjang yang berbeda, orang mungkin ingin memvalidasi panjang sebagai bagian dari pemrosesan yang berbeda untuk setiap jenis paket, tetapi memvalidasi checksum sebagai bagian dari logika umum terlebih dahulu. Jika paket kurang panjang diterima, tidak masalah apakah perhitungan checksum melaporkan "baik" atau "buruk", tetapi tidak boleh macet.