Является ли конструктор по умолчанию инициализацией встроенных типов?

Создает ли конструктор по умолчанию (созданный компилятором) встроенные типы?

Ответ 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 любых родителей.