2012-01-08 6 views
5

Почему GCC 4.7 жалуется при создании экземпляра класса внутри функции (с указателем)?GCC warning [Wuninitialized]

Плохо:

#include "foo.h" 

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

    return 0; 
} 

main.cpp: В функции члена 'INT Foo()': main.cpp: 21: 52: предупреждение: 'Fn' могут быть использованы в этом неинициализированным функция [-Wuninitialized]

Хорошо:

#include "foo.h" 

Foo *foo; 

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

    return 0; 
} 

Хорошо:

#include "foo.h" 

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

    return 0; 
} 
+1

Статические переменные инициализируются значением, поэтому второй фрагмент не вызывает предупреждения. В остальном заберите хорошую книгу о C++. –

+0

Не могли бы вы позаботиться о публикации ошибок точно так же, как сообщается компилятором для точного кода, который вы опубликовали. "main.cpp: В функции-члена 'int foo()': main.cpp: 21: 52: warning: 'fn' может использоваться неинициализированным в этой функции [-Wuninitialized]« Это не имеет смысла, 'foo' is not функция, не говоря уже о функции-члена, и 'fn' не является переменной. –

+0

Похоже, что имена 'foo' и' fn' были отменены в скопированном вами сообщении об ошибке. Либо это, либо сообщения компилятора C++ достигли нового уровня неправильного направления. – user268396

ответ

6

Там разница между Foo * foo; и Foo foo; Первый объявляет указатель к Foo, то второй объявляет & вызывает по умолчанию-конструктор в Foo с.

EDIT: Возможно, вы хотели написать Foo * foo= new Foo();, чтобы выделить Foo в кучу, которая может пережить вызов функции.

2

Foo* foo; foo->method() является никогда хорошо. foo - неинициализированный указатель, который потенциально указывает на мусор, и поэтому ваш код демонстрирует неопределенное поведение. Лучше всего вы можете надеяться, что компилятор предупреждает об этом или ошибки. Если это не так, то, по крайней мере, надеемся, что запущенная программа выйдет из строя.

2

В вашем плохом примере foo - это локальная переменная с типом указателя, которая не инициализируется автоматически. В class Foo в вашем правильном примере - это, инициализированный с использованием конструктора по умолчанию.

Ваш первый »хороший« пример инициализирует указатель с 0, потому что foo является глобальной переменной. Это приведет к неопределенным поведением во время выполнения, так как foo не указывает на объект.

2

потому что, как предупреждает предупреждение, оно неинициализировано. пока нет объекта. на самом деле значение foo в вашем первом примере не определено. он будет иметь значение, которое находится в памяти, где живет foo.

Чтобы уточнить, foo (который вы видите как Foo *) на самом деле является int. значение int должно быть адресом для объекта типа Foo. Чтобы сделать это, вы должны присвоить ему адрес foo. один делать это, чтобы создать его экземпляр с новым:

Foo* foo = new Foo; 

new возвращает адрес, по которому был создан новый объект Foo. это удалит ваше предупреждение :)

5

Первый (плохой), foo указывает на указатель мусора. Вы можете удалить предупреждение, инициализируя его как Foo* foo = NULL;, но затем вы получите сообщение об ошибке при попытке разыменовать его (ошибка времени выполнения).

Второй (хороший) не жалуется, потому что C автоматически инициализирует переменные в области единицы перевода до NULL или 0 или соответствующий эквивалент, если они еще не инициализированы.

Последний (хороший) человек не жалуется, потому что вы вызываете метод объекта, а назначение указателя функции выполняется компилятором, аналогичным, но не таким, как номер 2. Таким образом, компилятор уже знает адрес метода method и присвоил этот адрес соответствующему адресу в структуре Foo.