ISO C ++ 03 настолько авторитетен, насколько это возможно:
POD-структура - это агрегатный класс, который не имеет нестатических членов-данных типа non-POD-struct, non-POD-union (или массива таких типов) или ссылки, и не имеет пользовательского назначения копирования оператор и нет пользовательского деструктора. Аналогично, POD-объединение - это совокупное объединение, которое не имеет нестатических членов-данных типа non-POD-struct, non-POD-union (или массива таких типов) или ссылки, и не имеет пользовательского оператора назначения копирования и нет пользовательского деструктора. POD-класс - это класс, который является POD-структурой или POD-объединением.
Арифметические типы (3.9.1), типы перечисления, типы указателей и указатели на типы элементов (3.9.2) и cv-квалифицированные версии этих типов (3.9.3) вместе называются скалярными типами. Скалярные типы, типы POD-структур, типы POD-объединения (раздел 9), массивы таких типов и cv-квалифицированные версии этих типов (3.9.3) вместе называются типами POD.
Инициализация объекта типа T с нуля означает:
- если T - скалярный тип (3.9), объекту присваивается значение 0 (ноль), преобразованное в T;
- если T является типом класса, не являющимся объединением, каждый нестатический член данных и каждый базовый класс
подобъект инициализируется нулями;
- если T является типом объединения, первый именованный элемент данных объекта инициализируется нулями;
- если T является типом массива, каждый элемент инициализируется нулями;
- если T является ссылочным типом, инициализация не выполняется.
Инициализация по умолчанию объекта типа T означает:
- если T является типом класса, отличным от POD (раздел 9), вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);
- если T является типом массива, каждый элемент инициализируется по умолчанию;
- в противном случае объект инициализируется нулями.
Инициализация значения объекта типа T означает:
- если T является типом класса (раздел 9) с объявленным пользователем конструктором (12.1), то вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);
- если T является типом класса без объединения без конструктора, объявленного пользователем, то каждый нестатический член данных и компонент базового класса в T инициализируется значением;
- если T является типом массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулями
Каждый объект статической длительности хранения должен быть инициализирован нулем при запуске программы перед любой другой инициализацией. [Примечание: в некоторых случаях дополнительная инициализация выполняется позже.]
Объект, инициализатором которого является пустой набор скобок, т. Е. (), Должен быть инициализирован значением.
Если для объекта не указан инициализатор, и объект относится к (возможно, cv-квалифицированному) не относящемуся к POD типу класса (или его массиву), объект должен инициализироваться по умолчанию; если объект имеет константный тип, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если для нестатического объекта не указан инициализатор, объект и его подобъекты, если таковые имеются, имеют неопределенное начальное значение); если объект или какой-либо из его подобъектов имеют константный тип, программа некорректна.
Для вашего примера int
определенно является типом POD (это арифметический тип), и, следовательно, локальное поле или поле типа int
при отсутствии инициализатора будет иметь неопределенное значение. Для Foo
это зависит от того, как оно определено - грубо говоря, если у него нет конструктора, и все его члены имеют типы POD, то он сам является типом POD, и инициализация также не происходит. В противном случае вызывается конструктор по умолчанию. Даже в этом случае это не означает, что члены инициализированы - правила являются рекурсивными, поэтому члены POD не-POD-типа не будут инициализированы, если только конструктор этого типа специально не сделает этого (в списке инициализаторов ).
Статические переменные и поля во всех случаях будут инициализироваться нулями. Обратите внимание, что это также относится и к не POD - это означает, что статическая переменная типа класса гарантированно рекурсивно установит для всех полей значение (T)0
даже до запуска ее конструктора.
Удобный прием для инициализации по умолчанию любого агрегатного типа POD заключается в использовании {}
в инициализаторе - обратите внимание, что он работает как со структурами, так и с массивами:
char s[10] = {}; // all elements default-initialized
Foo foo = {}; // all fields recursively default-initialized