Является ли новый int [10] () допустимым c ++? - PullRequest
26 голосов
/ 18 марта 2010

Пытаясь ответить на этот вопрос, я обнаружил, что код int* p = new int[10](); прекрасно компилируется с компилятором VC9 и инициализирует целые числа равными 0. Поэтому мои вопросы:

  1. Прежде всего, это действительный C ++ или это расширение Microsoft?
  2. Гарантируется ли инициализация всех элементы массива?
  3. Кроме того, есть ли разница, если я сделать new int; или new int();? Есть ли последняя гарантия инициализации переменная?

Ответы [ 4 ]

29 голосов
/ 18 марта 2010

Прежде всего, это действительный C ++ или расширение Microsoft?

Это действительно в C ++, соответствующая часть стандарта - 5.3.4, с первым параграфом, содержащим грамматику

Гарантируется ли инициализация всех элементов массива?

Да. Пункт 5.3.4 / 15 гласит, что

Новое выражение, которое создает объект типа T, инициализирует этот объект следующим образом:

...

  • Если новый инициализатор имеет форму (), элемент инициализируется значением (8.5)

где значение, инициализированное для POD, означает инициализацию с нуля.

Кроме того, есть ли разница, если я сделаю новый int; или новый int () ;? Последний гарантирует инициализацию переменной?

Да, они разные. Согласно приведенной выше цитате new int() инициализирует целое число нулем. В предыдущем блоке того же абзаца:

Если новый инициализатор опущен:

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

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

, поэтому new int не будет инициализировать память.

2 голосов
/ 18 марта 2010

от стандарта. «Инициализация по умолчанию объекта типа T означает: - если T является типом класса не POD [случай как вектор], конструктор по умолчанию для T называется. "

Обозначение конструктора T() используется для выражения значения по умолчанию для типа T и того, что оно равно нулю для встроенных типов и конструктора по умолчанию для пользовательских типов. Конструкция POD() производит инициализацию значения в соответствии со стандартом stdandard, в результате чего все члены и подчиненные элементы либо создаются по умолчанию, либо инициализируются нулями.

Вот почему ваше утверждение является законным, но инициализировано ли оно нулем согласно стандарту; нужен подробный поиск ИМХО.

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

EDIT: -

struct S { int x; };

void f () {
   S s1;       // s1.x is uninitialized here
   S s2 = S(); // s2.x is zero here
}

Я думаю, что мы часто составляем нашу собственную интерпретацию того, что означает конструкция по умолчанию, применяемая к встроенным типам; потому что стандарт C ++ не определяет его (по крайней мере, я не смог его найти) и я помню Stroustrup или Josuttis говорят, что это означает T(), который описывается как « ноль преобразуется в тип T » для встроенных типов.

Поскольку int* является встроенным типом, он инициализируется нулем.

Но я действительно не уверен.

1 голос
/ 18 марта 2010
  1. Это допустимый C ++ в соответствии с пунктом 5.3.4 / 1, который здесь трудно процитировать из-за специального форматирования.

  2. Согласно 5.3.4 / 15, элемент инициализируется значением, если используется форма (), см. Параграф 8.5, но краткий ответ - да.

  3. Да, есть разница в первом случае, переменная не инициализируется значением и может быть чем угодно, во втором случае ее значение инициализировано и будет равно нулю.

0 голосов
/ 18 марта 2010

Если я могу немного угадать (я уверен, что меня поправят, если я ошибаюсь):

Последний () выполняет инициализацию значения (как его называют в стандарте), что делает целое число в этом случае значением 0.

Это довольно новое дополнение к стандарту (C ++ 03?), Поэтому старые компиляторы могут его не поддерживать и оставлять его неинициализированным.

Я помню, что получал много предупреждений об этом при переходе с MSVS 2003 на 2005 (я думаю), где компилятор сказал, что "этот элемент будет инициализирован нулем сейчас, а не раньше".

...