2011-12-16 11 views
6

Kiedy czytam standard C++, wygląda na to, że poniższy kod jest idealnie zgodny z normą.Dlaczego można wskoczyć w zakres obiektu typu skalarnego bez inicjalizatora?

int main() { 
    goto lol; 
    { 
     int x; 
lol: 
     cout << x << endl; 
    } 
} 

// OK 

[n3290 6.7/3] Możliwe jest przeniesienie na blok, a nie w sposób, który omija zgłoszeń z inicjalizacji. Program, który skacze od punktu, w którym zmienna z automatycznym okres przechowywania jest nie w zakresie do punktu, gdzie jest zasięg jest źle sformułowane chyba zmienna ma skalarnego typu, typ klasy z trywialny domyślny konstruktora i trywialny destruktor, wersja z kwalifikacjami cv jednego z tych typów lub tablica jednego z poprzednich typów i jest zadeklarowana jako bez inicjalizatora.

Dlaczego to powinno działać? Czy nie jest jeszcze niebezpiecznie przeskakiwać jego definicję i używać undefined x? I dlaczego istnienie inicjalizatora ma jakieś znaczenie?

Odpowiedz

7

Tak czy inaczej, użyjesz niezainicjowanej wersji x, ponieważ int x; jest niezainicjowana, tak jak to się stanie. Istnienie inicjalizatora sprawia oczywiście różnicę, ponieważ pominiesz to. int x = 5; na przykład inicjuje x, więc może to mieć znaczenie, jeśli przeskoczyłeś to, czy nie.

+0

Ale problem polega na tym, że niezależnie od inicjalizatora, x nie jest zdefiniowany, ponieważ jego definicja i tak jest pomijana. Czyż nie? –

+0

@EricZ: Definicja nadal występuje. 'goto' jest działaniem wykonawczym, pomija tylko zachowanie środowiska wykonawczego, takie jak inicjalizacja. – GManNickG

+0

@GMan, zgadza się! Dzięki;) –

2

Czy nie jest jeszcze niebezpieczne przeskoczyć definicję i użyć niezainicjowanego x?

Jednak i tak niezainicjowany byłby x, ponieważ został zadeklarowany bez inicjalizatora! Tak więc goto może przeskakiwać nad instrukcjami przypisania, które ustawiają (sortowanie-inicjowania) x, ale nie jest zaskakujące, że goto może pominąć instrukcje przypisania; a sama deklaracja w rzeczywistości nie ma żadnego znaczenia, chyba że istnieje inicjator.

+1

+1 * sama deklaracja niczego nie robi *. To kluczowy punkt. Bez inicjatora nie generuje się kodu. Reguły zapewniają, że w rzeczywistości nie pomijasz żadnego kodu. –

+0

@Ernest, Ciekawi mnie, jak zdefiniowano x, ponieważ jego definicja została odrzucona? –

+2

Wyobraź sobie, że wolny rejestr procesora jest przeznaczony do przechowywania 'x'. To tylko księgowość w kompilatorze; nie ma nic fizycznie w wygenerowanym kodzie, który mówi "Register 17 to teraz' x'. " Teraz, jeśli 'x' zostanie zainicjowany, będziemy mieli kod do ustawienia wartości rejestru - ale jak już powiedzieliśmy, nie ma tego. –

Powiązane problemy