goto
Yıkıcıları ve nesneleri çağırmadan kod parçalarının üzerinden atladığı doğru mu?
Örneğin
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Olmaz x
sızdırılmış olabilir?
goto
Yıkıcıları ve nesneleri çağırmadan kod parçalarının üzerinden atladığı doğru mu?
Örneğin
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Olmaz x
sızdırılmış olabilir?
"Won't x be leaked"
geliyor? Türü, x
yerleşik bir veri türüdür. Neden daha iyi bir örnek seçmiyorsun?
goto
, otomatik depolama süresi değişkenlerinin bile bir şekilde "sızdırıldığını" düşünüyorlar. Senin ve benim bunun aksini bildiğimiz, tamamen konunun dışında.
int
sızıntı edemez, bu olabilir sızdırılmış olması . Örneğin: void f(void) { new int(5); }
bir int
.
Yanıtlar:
Uyarı: Bu yanıt yalnızca C ++ ile ilgilidir ; C'de kurallar oldukça farklı.
Olmaz
x
sızdırılmış olabilir?
Kesinlikle değil.
goto
C ++ 'ın yerleşik kapsam mekanizmalarını geçersiz kılmanıza izin veren bazı düşük seviyeli yapılar olan bir efsanedir . (Bir şey varsa, buna longjmp
eğilimli olabilir.)
Etiketlerle ( case
etiketler dahil) "kötü şeyler" yapmanızı önleyen aşağıdaki mekanizmaları düşünün .
İşlevler arasında geçiş yapamazsınız:
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
// error: label 'lol' used but not defined
[n3290: 6.1/1]:
[..] Bir etiketin kapsamı, içinde göründüğü işlevdir. [..]
Nesne ilklendirmesine atlayamazsınız:
int main() {
goto lol;
int x = 0;
lol:
return 0;
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘int x’
Atlarsan geri nesne başlatma karşısında, daha sonra nesnenin önceki "örneği" yok edilir :
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]:
[..] Bir döngüden, bir bloktan veya otomatik depolama süresi ile başlatılmış bir değişkeni geri geçerek transfer, transfer edilen ancak transfer edilen noktada olmayan noktada kapsam içinde olan otomatik depolama süresi olan nesnelerin yok edilmesini içerir . [..]
Açıkça başlatılmamış olsa bile bir nesnenin kapsamına atlayamazsınız:
int main() {
goto lol;
{
std::string x;
lol:
x = "";
}
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘std::string x’
... "karmaşık" yapı gerektirmedikleri için dilin üstesinden gelebileceği belirli nesne türleri dışında
int main() {
goto lol;
{
int x;
lol:
x = 0;
}
}
// OK
[n3290: 6.7/3]:
Bir bloğa transfer etmek mümkündür, ancak başlatma ile bildirimleri atlayacak şekilde değil. Otomatik depolama süresi olan bir değişkenin kapsam içinde olmadığı bir noktadan, değişken skaler tip, önemsiz bir varsayılan kurucuya sahip sınıf tipi ve önemsiz bir yıkıcıya sahip olmadığı sürece kötü biçimlendirilmiş bir noktaya sıçrayan bir program, a Bu türlerden birinin cv nitelikli sürümü veya önceki türlerden birinin dizisi ve bir başlatıcı olmadan bildirilir. [..]
Aynı şekilde, otomatik depolama süresi nesneler vardır değil "sızan" sizi goto
dışarı onların kapsamı :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
{
T t;
goto lol;
}
lol:
return 0;
}
// *T~T
[n3290: 6.6/2]:
Bir kapsamdan çıkıldığında (ne kadar başarılı olursa olsun), o kapsamda inşa edilen otomatik depolama süresine (3.7.3) sahip nesneler, yapımlarının tersi sırada imha edilir. [..]
Yukarıdaki mekanizmalar goto
bunun dili kırmanıza izin vermemesini sağlar.
Tabii ki, bu otomatik olarak anlamına gelmez sen kullanımı "gereken" goto
Herhangi bir sorunun, ancak does neredeyse inanmak ortak efsane açar insanlar olarak "kötü" olarak olmadığını ortalama.