Инициализация инициализации по умолчанию С++ и инициализация значения: которая есть, которая вызывается, когда и как надежно инициализировать член типа шаблона

Мой вопрос несколько перекрывается с этим и несколькими другими подобными. У них есть отличные ответы, но я их прочитал, и я все еще смущен, поэтому, пожалуйста, не рассматривайте этот вопрос как дубликат.

Итак, у меня есть следующий код:

class A {
    public: int _a;
}

void main()
{
    A inst1;
    A* inst2 = new A;
    A* inst3 = new A();
}

_a остается неинициализированным в inst1 и inst2 и инициализируется на 0 в inst3. Какая инициализация называется, и почему код работает так, как он есть? Пожалуйста, учтите, что у меня нет стандарта С++ 03, но у меня есть последний проект С++ 11 (я программирую по стандарту '03, хотя), поэтому цитаты из стандарта '03 или ссылки на '11 приветствуются.

Р. S. Первоначальная задача этого исследования состояла в том, чтобы правильно zeto-инициализировать член произвольного типа шаблона T.

Ответ 1

Не так сложно:

A x;
A * p = new A;

Эти две инициализации по умолчанию. Поскольку у вас нет пользовательского конструктора, это означает, что все члены инициализируются по умолчанию. По умолчанию инициализация фундаментального типа типа int означает "без инициализации".

Далее:

A * p = new A();

Это инициализация значений. (Я не думаю, что существует автоматическая версия этого в С++ 98/03, хотя в С++ 11 вы можете сказать A x{};, и эта инициализация скобок становится инициализацией значения. Более того, A x = A(); достаточно близко практически, несмотря на то, что вы выполняете копирование, или A x((A())), несмотря на прямую инициализацию.)

Опять же, в вашем случае это означает, что все члены инициализируются значением. Инициализация значений для фундаментальных типов означает нулевую инициализацию, которая, в свою очередь, означает, что переменные инициализируются до нуля (которые имеют все основные типы).

Для объектов типа класса, как инициализация по умолчанию, так и инициализация значения вызывают конструктор по умолчанию. То, что происходит тогда, зависит от списка инициализаторов конструктора, и игра продолжается рекурсивно для переменных-членов.

Ответ 2

Да, A inst4 (); рассматривается как объявление функции. std::string str(); должен быть таким же (т.е. я думаю, вы ошибочно считали, что это сработало).

По-видимому (из здесь), С++ 03 будет иметь inst3._a be 0, но С++ 98 оставил бы его неинициализированным.