2010-07-05 14 views
37

Rozważmy następujący kod:Idź z bloku: czy wywoływane są destruktory?

void foo() 
{ 
    { 
     CSomeClass bar; 

     // Some code here... 

     goto label; 

     // and here... 
    } 

label: 
    // and here... 
} 

Will destruktor z barem nazwać?

+0

Dlaczego musisz to wiedzieć? 'goto' ma sens w wygenerowanym kodzie, ale i tak można i należy unikać obiektów z destruktorami. – MSalters

+13

@MSalters: to nie robi żadnego sensu, dlaczego powinieneś unikać obiektów z destruktorami? –

+1

@Viktor: Pozwól mi rozwinąć drugą część zdania: _W wygenerowanym kodzie, możesz i powinieneś unikać obiektów z destruktorami. Kanoniczne użycie 'goto' jest w wygenerowanym kodzie FSM. Tutaj skoki występują w tył i w przód, bez względu na stany kodów stanów, które akurat znajdują się w środku. Stany FSM po prostu nie są liniowe, ale musi to być kod C++. – MSalters

Odpowiedz

52

C++ standard mówi:

na wyjściu z zakresu (jednak dokonany), destruktory (12.4) są nazwie dla wszystkich budowanych obiektach z automatycznym czas przechowywania (3.7.2) (o nazwie o bjects lub temporaries), które są zadeklarowane w tym zakresie, w w odwrotnej kolejności do ich deklaracji .

Tak więc odpowiedź brzmi "tak".

+0

Dzięki. Tego właśnie potrzebowałem. –

9

1) Tak. 2) Nie rób tego.

Opracowanie: koncepcyjnie, nie różni się to od pozostawiania pętli przez break. goto jest jednak mocno, zdecydowanie odradzane. Używanie goto prawie nigdy nie jest konieczne, a każde użycie powinno zostać sprawdzone, aby dowiedzieć się, co się dzieje.

+0

Doskonała odpowiedź. – Mizipzor

+1

2) robisz to, kiedy faktycznie uciekasz z pętli. –

+14

W rzeczywistości, goto ma sens w kilku okolicznościach. –

21

Tak, będą one wywoływane.

Aktualizacja: (.. To jest w porządku, aby to zrobić, GOTOS nie jest gorszy niż rzucanie obojętne wyjątki lub używając bools/IFS, aby wydostać się z rzeczy Prosty goto wewnątrz funkcji nie sprawiają, że kod spaghetti)

+7

+1, aby zanegować egoistycznego ucznia, który poczuł potrzebę zejścia, ponieważ osobiście uważają, że goto są złe. Gotosy mają ważne zastosowania, ludzie, niezależnie od tego, co powiedzieli ci profesorowie. – KevenK

+2

"W porządku to zrobić, gotos nie jest gorszy niż rzucanie fałszywych wyjątków lub używanie bool/ifs, aby wydostać się z rzeczy" Rzucanie wyjątku obojętnego jest okropnym sposobem na to (wyrzucanie wyjątków jest generalnie bardzo kosztowne) i jeśli jest pomiędzy to i lepsze, zdecydowanie wolę gotów. Jednak pisanie funkcji dla tych przypadków jest z pewnością najlepszą drogą. – stinky472

+1

@KevinK - Gotos może mieć ważne zastosowania teoretycznie, ale są one niezwykle rzadkie w praktyce. Twierdzę, że jeśli wygląda na to, że musisz użyć goto, sytuacja przynajmniej zasługuje na dokładne sprawdzenie. A jeśli chodzi o początkujących programistów, sugerowałbym, aby ich unikać, to dobra dyscyplina do nauki. – jwismar

4

Tak, jak mówią wszyscy inni. C++ określa/nakazuje to.

Ale tylko dodać do tego, dla kompletności: jeśli goto używa computed- goto rozszerzenie znaleźć w niektórych kompilatory - gcc, szczęk, być może inne, ale nie tym MSVC ostatni Wiedziałem - czy destruktor obiektu zostanie nazwany jest dość mglisty. Kiedy goto idzie do pojedynczej lokalizacji, jest bardzo jasne, jakie destruktory muszą zostać wywołane przed transferem sterowania. Ale z obliczonym goto, różne destruktory mogą wymagać dynamicznego wywołania, aby dać "oczekiwaną" semantykę. Nie jestem pewien, jakie kompilatory, które implementują to rozszerzenie, w tych przypadkach. Moją pamięcią jest to, że klang ostrzega, gdy obliczony obiekt może pozostawić zakres z obiektem z nie-triwalnym destruktorem, twierdząc, że destruktor nie zostanie wywołany. W niektórych przypadkach może być dobrze, w innych nie. Nie wiem od ręki, co robią inne kompilatory. Po prostu pamiętaj o problemie, jeśli chcesz używać obliczonych goto s w porozumieniu z obiektami z nietrywialnymi destruktorami.

+0

Dzięki. Korzystam tylko z obliczonych gotów z C i w bardzo rzadkich sytuacjach. –

Powiązane problemy