Создание объекта стека на C ++ - Альтернативный синтаксис

Возможный дубликат:
Что означают следующие фразы в C ++: нулевое значение, инициализация по умолчанию и инициализация значения?

Меня смущает проблема в C ++.

При создании объекта в стеке с использованием конструктора по умолчанию я думал, что любой из следующих двух синтаксических обозначений даст тот же результат:

class MyClass { public: int i; }
int main()
{
  MyClass a = MyClass();
  MyClass b;
}

Однако первый синтаксис инициализирует поле нулем, тогда как второй оставляет поле неинициализированным. Итак, мои вопросы:

  1. Почему это так? Я думал, что поля в C ++ не должны инициализироваться автоматически.
  2. Есть ли другие различия между двумя синтаксисами?
  3. Есть ли у этих вариантов синтаксиса отдельные имена, чтобы отличать их друг от друга?

В настоящее время я использую Microsoft Visual C ++ 2010 Express. Спасибо!


person Mike    schedule 28.06.2011    source источник
comment
Вы видите поведение C ++ 03. В C ++ 98 они оба оставили бы его неинициализированным, если бы у него не было конструктора. Пару дней назад был почти такой же вопрос.   -  person Mark B    schedule 28.06.2011
comment
@Mark B: Я полностью не согласен. Вам нужно будет знать эти фразы, чтобы ответить на этот вопрос. Абсолютно актуально, но не дубликат.   -  person Puppy    schedule 28.06.2011
comment
@DeadMG: Никто не обвиняет Майка в том, что он не нашел этот вопрос, но ему все еще отвечают ответы на другой вопрос, поэтому я думаю, что это действительно должно быть закрыто как обман. (Этот вопрос касается в точности тех же вопросов, что и предыдущие вопросы по этой теме.)   -  person sbi    schedule 28.06.2011


Ответы (2)


В первом случае вы инициализируете копированием a из экземпляра MyClass с инициализацией значения. Из стандарта C ++ 03, §8.5 / 7:

Объект, инициализатором которого является пустой набор круглых скобок, то есть (), должен быть инициализирован значением.

И из §8.5 / 5:

инициализировать значение объекта типа T означает:

  • если T является типом класса с конструктором, объявленным пользователем, то вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
  • если T является типом класса без объединения без конструктора, объявленного пользователем, то каждый нестатический член данных и компонент базового класса T инициализируется значением;
  • если T является типом массива, то каждый элемент инициализируется значением;
  • в противном случае объект инициализируется нулем

Для инициализации нуля объекта типа T означает:

  • если T является скалярным типом, объекту присваивается значение 0 (ноль), преобразованное в T;
  • если T - тип класса, не являющегося объединением, каждый нестатический член данных и каждый подобъект базового класса инициализируются нулем;
  • если T является типом объединения, первый именованный элемент данных объекта) инициализируется нулем;
  • если T является типом массива, каждый элемент инициализируется нулем;
  • если T - ссылочный тип, инициализация не выполняется.

Во втором случае вы объявляете b таким образом, чтобы он был default-initialize d, если MyClass не был типом POD - §8.5 / 5:

инициализация по умолчанию для объекта типа T означает:

  • если T не является типом класса POD, вызывается конструктор по умолчанию для T (и инициализация неправильно сформирована, если T не имеет доступного конструктора по умолчанию);
  • если T является типом массива, каждый элемент инициализируется по умолчанию;
  • в противном случае объект инициализируется нулем.

Однако, поскольку MyClass является типом POD, b не инициализирован - §8.5 / 9:

Если для объекта не указан инициализатор, и объект относится к типу (возможно, cv-квалификационному), не относящемуся к классу POD (или его массиву), объект должен быть инициализирован по умолчанию; если объект имеет тип, уточненный константой, базовый тип класса должен иметь конструктор по умолчанию, объявленный пользователем. В противном случае, если для нестатического объекта не указан инициализатор, этот объект и его подобъекты, если таковые имеются, имеют неопределенное начальное значение; если объект или любой из его подобъектов относятся к типу с квалификацией const, программа имеет неправильный формат.

person ildjarn    schedule 28.06.2011
comment
Спасибо за этот ответ. Очень информативно. - person Mike; 30.06.2011

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

UDT, которые не делают ничего безумного, не должны требовать первый синтаксис, и нормально использовать второй.

person Puppy    schedule 28.06.2011
comment
Пользовательские типы всегда инициализируются некорректно. - person fredoverflow; 28.06.2011