Benarkah itu goto
melompati bit kode tanpa memanggil destruktor dan benda-benda?
misalnya
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Tidak x
akan bocor?
Benarkah itu goto
melompati bit kode tanpa memanggil destruktor dan benda-benda?
misalnya
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Tidak x
akan bocor?
"Won't x be leaked"
maksudnya Jenis x
adalah tipe data bawaan. Mengapa Anda tidak memilih contoh yang lebih baik?
goto
, mereka berpikir bahwa bahkan variabel durasi penyimpanan otomatis entah bagaimana "bocor". Bahwa Anda dan saya tahu sebaliknya sama sekali tidak penting.
int
bisa bocor, bisa juga bocor . Misalnya: void f(void) { new int(5); }
kebocoran int
.
Jawaban:
Peringatan: Jawaban ini berkaitan dengan C ++ hanya ; aturannya sangat berbeda di C.
Tidak
x
akan bocor?
Tidak, sama sekali tidak.
Ini adalah mitos yang goto
merupakan beberapa konstruksi tingkat rendah yang memungkinkan Anda untuk mengganti mekanisme pelingkupan bawaan C ++. (Jika ada, itu longjmp
mungkin rentan terhadap ini.)
Pertimbangkan mekanisme berikut yang mencegah Anda melakukan "hal buruk" dengan label (yang termasuk case
label).
Anda tidak dapat melompati fungsi:
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
// error: label 'lol' used but not defined
[n3290: 6.1/1]:
[..] Ruang lingkup label adalah fungsi di mana label itu muncul. [..]
Anda tidak dapat melompati inisialisasi objek:
int main() {
goto lol;
int x = 0;
lol:
return 0;
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘int x’
Jika Anda melompat kembali melintasi inisialisasi objek, "instance" objek sebelumnya akan dimusnahkan :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
int x = 0;
lol:
T t;
if (x++ < 5)
goto lol;
}
// Output: *T~T*T~T*T~T*T~T*T~T*T~T
[n3290: 6.6/2]:
[..] Transfer keluar dari loop, keluar dari blok, atau kembali melewati variabel yang diinisialisasi dengan durasi penyimpanan otomatis melibatkan penghancuran objek dengan durasi penyimpanan otomatis yang berada dalam lingkup pada titik yang ditransfer dari tetapi tidak pada titik yang ditransfer ke . [..]
Anda tidak dapat melompat ke dalam cakupan suatu objek, meskipun objek tersebut tidak dijalankan secara eksplisit:
int main() {
goto lol;
{
std::string x;
lol:
x = "";
}
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘std::string x’
... kecuali untuk jenis objek tertentu , yang dapat ditangani oleh bahasa karena tidak memerlukan konstruksi "rumit":
int main() {
goto lol;
{
int x;
lol:
x = 0;
}
}
// OK
[n3290: 6.7/3]:
Dimungkinkan untuk mentransfer ke dalam blok, tetapi tidak dengan cara yang mengabaikan deklarasi dengan inisialisasi. Sebuah program yang melompat dari titik di mana sebuah variabel dengan durasi penyimpanan otomatis tidak dalam cakupan ke titik di mana ia berada dalam ruang lingkup tidak terbentuk kecuali variabel tersebut memiliki tipe skalar, tipe kelas dengan konstruktor standar yang sepele dan destruktor sepele, a versi yang memenuhi syarat cv dari salah satu jenis ini, atau larik dari salah satu jenis sebelumnya dan dideklarasikan tanpa penginisialisasi. [..]
Demikian juga, objek dengan durasi penyimpanan otomatis yang tidak "bocor" ketika Anda goto
keluar dari ruang lingkup mereka :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
{
T t;
goto lol;
}
lol:
return 0;
}
// *T~T
[n3290: 6.6/2]:
Saat keluar dari ruang lingkup (bagaimanapun tercapai), objek dengan durasi penyimpanan otomatis (3.7.3) yang telah dibangun dalam lingkup itu dihancurkan dalam urutan kebalikan dari konstruksi mereka. [..]
Mekanisme di atas memastikan bahwa goto
Anda tidak merusak bahasa.
Tentu saja, ini tidak secara otomatis berarti bahwa Anda "harus" menggunakan goto
untuk setiap masalah tertentu, tetapi ini berarti bahwa masalah itu hampir tidak "jahat" seperti yang diyakini oleh mitos umum.