По сути, почему это так:
auto p1 = new int[10]{5};
но это не так
auto p1 = new int[10](5);
И в целом, каковы правила для инициализатора нового выражения?
Я нашел следующее:
— Если новый инициализатор опущен, объект инициализируется по умолчанию (8.5). [Примечание: если инициализация не выполняется, объект имеет неопределенное значение. — конец примечания] — В противном случае новый инициализатор интерпретируется в соответствии с правилами инициализации 8.5 для прямой инициализации.
Так что второй случай недействителен, потому что что-то вроде T((5))
неверно (прямая инициализация из выражения (5)
)? Или в чем причина?
РЕДАКТИРОВАТЬ: хорошо, мое предложение (())
вещь кажется глупой, потому что я не вижу причин, почему это должно применяться только к массиву new-expression.
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);
,
Других решений пока нет …