Рассмотрим эту программу:
struct S {
int m;
};
int main() {
S s_arr[1]{0};
S *s_new = new S[1]{0};
int i_arr[1][1]{0};
int (*i_new)[1] = new int[1][1]{0};
return 0;
}
Я думаю, что все четыре переменные в основной функции должны быть инициализированы с использованием агрегированной инициализации.
Однако GCC принимает только s_arr
и i_arr
, но отклоняет s_new
и i_new
, отчеты (g ++ 8.3.0 в Ubuntu):
test.cpp: In function ‘int main()’:
test.cpp:7:26: error: could not convert ‘0’ from ‘int’ to ‘S’
S *s_new = new S[1]{0};
^
test.cpp:9:38: error: array must be initialized with a brace-enclosed initializer
int (*i_new)[1] = new int[1][1]{0};
^
test.cpp:9:38: error: array must be initialized with a brace-enclosed initializer
(примечание: последняя повторяющаяся строка создается g ++)
Я также тестировал godbolt, ни одна из версий gcc от 6.1 до 9.2 не может скомпилировать эту программу. Версии 6.x и 7.x также выдают сообщение: «извините, нереализовано: невозможно инициализировать многомерный массив с инициализатором» для i_new
.
Изменение {0}
на {{0}}
разрешает как s_new
, так и inew
для всех версий GCC, протестированных на Godbolt (с 6.1 по 9.2). Я могу это понять, поскольку оба S[1]
и int[1][1]
являются агрегатными типами, тип элемента которых является субагрегатом (массив S
; массив массивов). Однако C ++ позволяет опускать эти фигурные скобки, а GCC принимает s_arr
и i_arr
, где эти фигурные скобки опущены.
С другой стороны, clang 6.0.0 - clang 9.0.0 с радостью принимает исходную программу.
В спецификации C ++ 14 (gnu ++ 14 по умолчанию для GCC 6.5 / 7.4 / 8.3 / 9.2),
5.3.4 Новый / 17
Новое выражение, которое создает объект типа T, инициализирует этот объект следующим образом:
......
(17.2) - В противном случае новый инициализатор интерпретируется в соответствии с правилами инициализации 8.5 для прямой инициализации.
Новый инициализатор следует интерпретировать как прямую инициализацию. Поскольку s_arr
и i_arr
также инициализируются напрямую, я думаю, что они должны интерпретироваться одинаково, а исходная программа должна быть правильно сформирована.
Что мне здесь не хватает, или это ошибка GCC?
Я попытался выполнить поиск через GCC Bugzilla, но не нашел ничего подходящего.
{0}
часто вводит в заблуждение, так как это означает инициализацию нуля первого элемента и инициализацию значения остальных. Лучше просто использовать{}
или()
для инициализации значения всего объекта (это установит его в 0). Кстати, это тоже нормально компилируется на gcc. - person rustyx   schedule 29.09.2019