Предупреждение GCC [Wuninitialized] - PullRequest
5 голосов
/ 09 января 2012

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

Плохо:

#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;
}

Ответы [ 5 ]

6 голосов
/ 09 января 2012

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

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

5 голосов
/ 09 января 2012

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

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

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

2 голосов
/ 09 января 2012

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

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

Foo* foo = new Foo;

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

2 голосов
/ 09 января 2012

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

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

2 голосов
/ 09 января 2012

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

...