Инициализация типов 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