Инициализация типов POD по умолчанию в C++

Я знаю POD переменные инициализируются по умолчанию, а другие нет. (Типы POD включают int, float, указатели, объединения, массивы типов POD, структуры типов POD и т. д.)

как область и класс хранения влияют на инициализацию по умолчанию типов POD?

в частности, какое из следующих действий будет инициализировано неявно:

  • локальные переменные с автоматическим хранения
  • статический локальные переменные
  • статические глобальные переменные
  • внешние переменные
  • переменные, выделенные с помощью new
  • члены POD класса (без явной инициализации в конструкторе)

Я знаю, что существуют вопросы, касающиеся некоторых из этих ситуаций, но ни один всеобъемлющий (они касаются только конкретных ситуаций).

2 ответов


локальные переменные с автоматической продолжительностью хранения не инициализируются автоматически. Поскольку использование неинициализированных переменных производит неопределенное поведение, рекомендуется явно инициализировать переменные, даже если они избыточны.

о типах POD, которые инициализируются нулем, стандарт C++03 3.6.2 инициализация нелокальных объектов гласит:

§1 объекты статическое хранение продолжительность (3.7.1) должна быть ноль-инициализировать (8.5) перед любой другой инициализации. Нулевая инициализация и инициализация с постоянным выражением в совокупности называются статической инициализацией; все остальные инициализации-динамическая инициализация. Объекты типов POD (3.9) со статической длительностью хранения, инициализированные постоянными выражениями (5.19), должны быть инициализированы до любой динамической инициализации.

Так что это гарантировано по стандарту, что POD типы с статическая продолжительность хранения (независимо от их области) будет инициализирован нулем.

члены POD класса (без явной инициализации в конструкторе)

эта ситуация описана в 12.6.2 инициализация баз и членов, который заявляет (выбранные части):

Если нестатические элемент данных или базовый класс не называется идентификатор инициализатора mem (включая случай, когда нет списка инициализаторов mem, потому что у конструктора нет инициализатора ctor), затем:

- если сущность является нестатический элемент данных... и класс сущности является не-POD класс, объект по умолчанию-инициализировать (8.5)...

-в противном случае, объект не инициализируется...

после вызова конструктора для класса X имеет завершено, если член X не указан ни в инициализаторах mem конструктора, ни инициализирован по умолчанию, ни инициализирован значением, ни задано значение во время выполнения тела конструктора,член имеет неопределенное значение.

пример:

class C
{
public:
    C(int x, int z) : x(x), z(z) { }
    int x, y, z;
};

int main(void)
{
    C* c = new C(1,3);
    std::cout << c->y; // value of y is undetermined !!!
}

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

стручки, выделенные с new также инициализируется иногда - если вы сделаете явной инициализации:

int* x = new int();

создать int инициализации 0 С x указывая на него, тогда как

int* x = new int;

будет x укажите на неинициализированное int.

иногда-члены класса POD - они могут быть инициализированы явно (не будучи в конструкторе):

struct X
{
   int x;
};

X x;        //x.x is not initialized
X y = X();  //y.x is 0