Apa yang terjadi di sini?
if(int a = Func1())
{
// Works.
}
if((int a = Func1()))
{
// Fails to compile.
}
if((int a = Func1())
&& (int b = Func2()))
)
{
// Do stuff with a and b.
// This is what I'd really like to be able to do.
}
Bagian 6.4.3 dalam standar 2003 menjelaskan bagaimana variabel yang dideklarasikan dalam kondisi pernyataan pemilihan memiliki ruang lingkup yang meluas hingga akhir substrat yang dikontrol oleh kondisi tersebut. Tapi saya tidak melihat di mana dikatakan apa pun tentang tidak dapat menempatkan tanda kurung di sekitar deklarasi, juga tidak mengatakan apa pun tentang hanya satu deklarasi per kondisi.
Batasan ini mengganggu bahkan dalam kasus di mana hanya satu deklarasi dalam kondisi yang diperlukan. Pertimbangkan ini.
bool a = false, b = true;
if(bool x = a || b)
{
}
Jika saya ingin memasukkan 'if "-body scope dengan x disetel ke false maka deklarasi membutuhkan tanda kurung (karena operator penugasan memiliki prioritas lebih rendah daripada logika OR), tetapi karena tanda kurung tidak dapat digunakan, diperlukan deklarasi x di luar tubuh, membocorkan deklarasi itu ke lingkup yang lebih besar daripada yang diinginkan. Jelas contoh ini sepele tetapi kasus yang lebih realistis adalah kasus di mana a dan b adalah fungsi yang mengembalikan nilai yang perlu diuji
Jadi, apakah yang ingin saya lakukan tidak sesuai dengan standar, atau apakah kompiler saya hanya merusak bola saya (VS2008)?
sumber
if
.if
bukan sebuah loop, ini adalah sebuah kondisional.while
sama seperti untukif
.if (int a = foo(), int b = bar(), a && b)
? Jika operator koma tidak kelebihan beban, standar mengatakan bahwa ekspresi dievaluasi dari kiri ke kanan, dan nilai hasil adalah ekspresi terakhir. Ia bekerja denganfor
inisialisasi loop, mengapa tidak di sini?if
kerjanya, dan sepertinya anggapan itu salah.Jawaban:
Pada C ++ 17 apa yang Anda coba lakukan akhirnya mungkin :
Perhatikan penggunaan dari
;
alih-alih,
untuk memisahkan deklarasi dan kondisi sebenarnya.sumber
Saya pikir Anda sudah mengisyaratkan masalah ini. Apa yang harus dilakukan kompilator dengan kode ini?
Operator "&&" adalah logika hubungan pendek AND. Artinya jika bagian pertama
(1==0)
ternyata salah, maka bagian kedua(bool a = false)
tidak perlu dievaluasi karena sudah diketahui bahwa jawaban akhirnya salah. Jika(bool a = false)
tidak dievaluasi, lalu apa yang harus dilakukan dengan kode nantia
? Akankah kita tidak menginisialisasi variabel dan membiarkannya tidak terdefinisi? Apakah kita akan menginisialisasinya ke default? Bagaimana jika tipe datanya adalah kelas dan melakukan ini memiliki efek samping yang tidak diinginkan? Bagaimana jika alih-alihbool
Anda menggunakan kelas dan tidak memiliki konstruktor default sehingga pengguna harus memberikan parameter - lalu apa yang harus kita lakukan?Berikut contoh lainnya:
Sepertinya batasan yang Anda temukan tampaknya masuk akal - ini mencegah terjadinya ambiguitas semacam ini.
sumber
Kondisi dalam pernyataan
if
atauwhile
dapat berupa ekspresi , atau deklarasi variabel tunggal (dengan inisialisasi).Contoh kedua dan ketiga Anda bukanlah ekspresi yang valid, maupun deklarasi yang valid, karena deklarasi tidak bisa menjadi bagian dari ekspresi. Meskipun akan berguna untuk dapat menulis kode seperti contoh ketiga Anda, ini akan membutuhkan perubahan signifikan pada sintaks bahasa.
Spesifikasi sintaks pada 6.4 / 1 memberikan kondisi berikut:
menentukan satu deklarasi, tanpa tanda kurung atau hiasan lainnya.
sumber
Jika Anda ingin memasukkan variabel dalam cakupan yang lebih sempit, Anda selalu dapat menggunakan tambahan
{ }
sumber
Bagian terakhir sudah berfungsi, Anda hanya perlu menulisnya sedikit berbeda:
sumber
Berikut adalah solusi buruk menggunakan perulangan (jika kedua variabel adalah bilangan bulat):
Tetapi ini akan membingungkan programmer lain dan ini adalah kode yang agak buruk, jadi tidak disarankan.
{}
Blok penutup sederhana (seperti yang telah direkomendasikan) jauh lebih mudah dibaca:sumber
Satu hal yang perlu diperhatikan, juga adalah ekspresi di dalam blok if yang lebih besar
tidak selalu dijamin untuk dievaluasi dengan cara kiri-ke-kanan. Satu bug yang agak halus yang saya hadapi pada hari itu berkaitan dengan fakta bahwa kompilator sebenarnya menguji kanan-ke-kiri alih-alih kiri-ke-kanan.
sumber
if(p && p->str && *p->str) ...
. Kanan-ke kiri akan mematikan dan tidak terselubung. Dengan operator lain - bahkan penugasan! - dan argumen pemanggilan fungsi Anda benar, tetapi tidak dengan operator sirkuit pendek.Dengan sedikit keajaiban templat Anda dapat mengatasi masalah tidak dapat mendeklarasikan banyak variabel:
(Perhatikan, ini menghilangkan evaluasi korsleting.)
sumber