Создает ли конструктор по умолчанию (созданный компилятором) встроенные типы?
Является ли конструктор по умолчанию инициализацией встроенных типов?
Ответ 1
Неявно определенный (по компилятору) конструктор по умолчанию класса не инициализирует элементы встроенных типов.
Однако вы должны иметь в виду, что в некоторых случаях инициализация экземпляра класса может выполняться другими способами. Не по умолчанию конструктор, ни конструктор вообще.
Например, существует распространенное неверное убеждение, что для класса C
синтаксис C()
всегда вызывает конструктор по умолчанию. В действительности же синтаксис C()
выполняет так называемую инициализацию значения экземпляра класса. Он будет вызывать только конструктор по умолчанию, если он объявлен пользователем. (Это в С++ 03. В С++ 98 - только если класс не является POD). Если класс не имеет объявленного пользователем конструктора, то C()
не будет вызывать предоставленный компилятором конструктор по умолчанию, а скорее выполнит специальный тип инициализации, который вообще не будет включать конструктор C
. Вместо этого он будет напрямую инициализировать значение каждого члена класса. Для встроенных типов это приводит к нулевой инициализации.
Например, если ваш класс не имеет объявленного пользователем конструктора
class C {
int x;
};
то компилятор неявно предоставит его. Конструктор, предоставленный компилятором, ничего не сделает, что означает, что он не инициализирует C::x
C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage
Тем не менее, следующие инициализации будут инициализировать нуль x
, поскольку они используют явный инициализатор ()
C c = C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(c.x == 0);
C *pc = new C(); // Does not use default constructor for `C()` part
// Uses value-initialization feature instead
assert(pc->x == 0);
Поведение инициализатора ()
в некоторых отношениях отличается от С++ 98 и С++ 03, но не в этом случае. Для вышеуказанного класса C
он будет таким же: ()
инициализатор выполняет нулевую инициализацию C::x
.
Другим примером инициализации, который выполняется без участия конструктора, является, конечно, агрегатная инициализация
C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);
C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);
Ответ 2
Для всех практических целей - нет.
Однако для реализаций, которые технически соответствуют стандарту С++, ответ заключается в том, что это зависит от того, является ли объект POD или нет, и от того, как вы его инициализируете. Согласно стандарту С++:
MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized
Однако в реальном мире это не очень хорошо поддерживается, поэтому не используйте его.
Соответствующими частями стандарта являются разделы 8.5.5 и 8.5.7
Ответ 3
Я не совсем понимаю, что вы имеете в виду, но:
struct A { int x; };
int a; // a is initialized to 0
A b; // b.x is initialized to 0
int main() {
int c; // c is not initialized
int d = int(); // d is initialized to 0
A e; // e.x is not initialized
A f = A(); // f.x is initialized to 0
}
В каждом случае, когда я говорю "не инициализировано", вы можете обнаружить, что ваш компилятор дает ему согласованное значение, но стандарт его не требует.
Много ручного размаха бросается вокруг, в том числе и мной, о том, как встроенные типы "по сути" имеют конструктор по умолчанию. Фактически инициализация по умолчанию и инициализация значений определяются в стандарте, которые я лично должен искать каждый раз. Только классы определены в стандарте, чтобы иметь неявный конструктор по умолчанию.
Ответ 4
В соответствии со стандартом, это не происходит, если вы явно не инициализируете в списке инициализаций
Ответ 5
Как заявили предыдущие ораторы - нет, они не инициализированы.
На самом деле это источник действительно странных ошибок, поскольку современные ОС, как правило, заполняют новые выделенные области памяти нулями. Если вы ожидаете этого, он может работать в первый раз. Тем не менее, по мере продолжения работы вашего приложения, delete
-ing и new
-ing объектов, вы рано или поздно окажетесь в ситуации, когда вы ожидаете нулей, но не имеет нулевого остатка от более раннего объекта.
Итак, почему это тогда, не все ли выделенные данные new
-ed? Да, но не всегда из ОС. ОС имеет тенденцию работать с более крупными фрагментами памяти (например, по 4 Мбайт за раз), поэтому все крошечные однословные-здесь-три байта-распределения и деаллокации обрабатываются в uyserspace и, следовательно, не обнуляются.
PS. Я написал "склонны к", т.е. Вы не можете даже полагаться на успех в первый раз...
Ответ 6
Технически он инициализирует их - используя свой конструктор по умолчанию, который, кстати, ничего не делает, кроме выделения памяти для них.
Если то, что вы хотели знать, - это то, что для них установлено значение 0 для int
s, или нет, тогда ответ "нет".
Ответ 7
Нет. Конструктор по умолчанию выделяет память и вызывает конструктор no-argument любых родителей.