2012-01-08 22 views
5

Dlaczego GCC 4.7 narzeka podczas tworzenia instancji klasy wewnątrz funkcji (ze wskaźnikiem)?Ostrzeżenie GCC [Wuninitialized]

Zła:

#include "foo.h" 

int fn() { 
    Foo *foo; 
    foo->method(); 

    return 0; 
} 

main.cpp W funkcji składowej 'Int foo()' main.cpp: 21: 52: uwaga: 'N' mogą być stosowane w tym niezainicjowanego funkcja [-Wuninitialized]

Dobre: ​​

#include "foo.h" 

Foo *foo; 

int fn() { 
    foo->method(); 

    return 0; 
} 

Dobre:

#include "foo.h" 

int fn() { 
    Foo foo; 
    foo.method(); 

    return 0; 
} 
+1

Zmienne statyczne są inicjowane wartością, więc drugi fragment nie powoduje ostrzeżenia. Co do reszty, wybierz dobrą książkę o C++. –

+0

Czy możesz zadać sobie pytanie, aby opublikować błędy dokładnie tak, jak zostały zgłoszone przez kompilator pod kątem kodu, który napisałeś. "main.cpp: W funkcji członka 'int foo()': main.cpp: 21: 52: ostrzeżenie: 'fn' może być użyty niezainicjowany w tej funkcji [-Wuninitialized]" To nie ma sensu, 'foo' nie jest funkcja, nie mówiąc już o funkcji członkowskiej, a 'fn' nie jest zmienną. –

+0

Wygląda na to, że nazwy "foo' i" fn' zostały odwrócone w skopiowanym komunikacie o błędzie. Albo te komunikaty kompilatora C++ osiągnęły nowy poziom błędnego ukierunkowania. – user268396

Odpowiedz

6

Jest różnica między Foo * foo; i Foo foo; pierwszych deklaruje wskaźnik do Foo, drugi deklaruje & wywołuje domyślny konstruktor-foo.

EDYCJA: Być może miałeś zamiar napisać Foo * foo= new Foo();, aby przydzielić Foo na stercie, który może przeżyć wywołanie funkcji.

2

Foo* foo; foo->method() to Nigdy dobrze. foo to niezainicjowany wskaźnik, który potencjalnie wskazuje na śmieci i jako taki Twój kod wykazuje niezdefiniowane zachowanie. Najlepszym pomysłem, jaki można uzyskać, jest kompilator ostrzegający lub błędny. Jeśli nie to, to co najmniej nadzieja, że ​​uruchomiony program zawiesza się.

2

W twoim złym przykładzie foo jest lokalną zmienną o typie wskaźnika, która nie jest inicjowana automatycznie. class Foo, w twoim prawidłowym przykładzie, , jest zainicjowany przy użyciu domyślnego konstruktora.

Twój pierwszy "dobry" przykład inicjalizuje wskaźnik za pomocą 0, ponieważ foo jest zmienną globalną. Powoduje to nieokreślone zachowaniew czasie wykonywania, ponieważ foo nie wskazuje obiektu.

2

ponieważ, jak ostrzega, nie jest inicjowana. nie ma jeszcze obiektu. faktycznie wartość foo w twoim pierwszym przykładzie jest niezdefiniowana. będzie mieć wartość, która znajduje się w pamięci, w której mieszka foo.

wyjaśnić, foo (które widzisz jako Foo *) jest rzeczywiście int. wartość int ma być adresem do obiektu typu Foo. aby tak było, musisz przypisać mu adres foo. jeden robi to do wystąpienia jej nowy:

Foo* foo = new Foo; 

new zwraca adres gdzie nowy obiekt Foo został utworzony. to usunie ostrzeżenie :)

5

Pierwszy (zły) jeden, foo wskazuje na wskaźnik śmieci. Możesz usunąć ostrzeżenie, inicjując go tak, jak Foo* foo = NULL;, ale wtedy pojawi się błąd, gdy spróbujesz usunąć z niego dereferencję (błąd wykonania).

Drugi (dobry) nie narzeka, ponieważ C automatycznie inicjuje zmienne w zakresie jednostki tłumaczeniowej na NULL lub 0 lub odpowiedni odpowiednik, jeśli nie zostały jeszcze zainicjalizowane.

Ostatni (dobry) nie narzeka, ponieważ wywołujesz metodę na obiekcie, a przypisanie wskaźnika funkcji jest wykonywane przez kompilator, podobnie, ale nie tak samo jak numer 2. Kompilator już wie adres metody method i przypisał ten adres do odpowiedniej lokalizacji w strukturze Foo.

Powiązane problemy