Direct-init против list-init в массиве new-expression

По сути, почему это так:

auto p1 = new int[10]{5};

но это не так

auto p1 = new int[10](5);

И в целом, каковы правила для инициализатора нового выражения?

Я нашел следующее:

— Если новый инициализатор опущен, объект инициализируется по умолчанию (8.5). [Примечание: если инициализация не выполняется, объект имеет неопределенное значение. — конец примечания] — В противном случае новый инициализатор интерпретируется в соответствии с правилами инициализации 8.5 для прямой инициализации.

Так что второй случай недействителен, потому что что-то вроде T((5)) неверно (прямая инициализация из выражения (5))? Или в чем причина?

РЕДАКТИРОВАТЬ: хорошо, мое предложение (()) вещь кажется глупой, потому что я не вижу причин, почему это должно применяться только к массиву new-expression.

7

Решение

1-й действует из-за инициализация списка (начиная с C ++ 11),

new T { arg1, arg2, ... }

а также

Если T является агрегатным типом, выполняется агрегатная инициализация.

int[10] тип массива, который принадлежит типу агрегата, то агрегатная инициализация выполняется,

Если количество пунктов инициализатора меньше, чем количество членов and bases (since C++17) или список инициализаторов полностью пуст, остальные члены and bases (since C++17) инициализируются by their default initializers, if provided in the class definition, and otherwise (since C++14) пустыми списками в соответствии с обычными правилами инициализации списков (которые выполняют инициализацию значений для типов, не относящихся к классам и неагрегированных классов с конструкторами по умолчанию, и инициализацию агрегатов для агрегатов). Если член ссылочного типа является одним из этих оставшихся членов, программа является некорректной.

Так auto p1 = new int[10]{5}; создаст указатель на массив, первый элемент которого инициализируется как 5остальные элементы инициализируются как 0,

2-й прямая инициализация, так new int[10](5); означает инициализировать массив int[10] с одного int 5 непосредственно; который недействителен.

На самом деле, для массив новое выражение Вы не можете указать непустой инициализатор в скобках.

Если тип является типом массива, массив объектов инициализируется.

  • Если инициализатор отсутствует, каждый элемент инициализируется по умолчанию
  • Если инициализатор представляет собой пустую пару скобок, каждый элемент инициализируется значением.
  • Если инициализатор представляет собой заключенный в скобки список аргументов, массив инициализируется агрегатно. (начиная с C ++ 11)

Так

auto p1 = new int[10];    // valid
auto p2 = new int[10]();  // valid
auto p3 = new int[10]{5}; // valid

auto p4 = new int[10](5); // invalid

РЕДАКТИРОВАТЬ

С точки зрения стандарта, как вы цитировали, [Expr.new] / 18:

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

  • Если новый инициализатор опущен, объект инициализируется по умолчанию ([dcl.init]). [Примечание: если инициализация не выполняется, объект
    имеет неопределенное значение. — конец примечания]

=> Применяется для auto p1 = new int[10];, приводит к инициализации по умолчанию.

  • В противном случае новый инициализатор интерпретируется в соответствии с правилами инициализации [dcl.init] для прямой инициализации.

А также [Dcl.init] / 17:

  • (17.1) Если инициализатором является (не заключенный в скобки) фигурный список инициализации или is = braced-init-list, объект или ссылка инициализируются списком.

=> Применяется для auto p3 = new int[10]{5};, приводит к инициализации списка, подробности объяснены выше.

  • (17.4) Если инициализатором является (), объект инициализируется значением.

=> Применяется для auto p2 = new int[10]();, приводит к инициализации значения.

  • (17.5) В противном случае, если тип назначения является массивом, программа является некорректной.

=> Применяется для auto p4 = new int[10](5);,

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]