GCC не поддерживает исключение фигурных скобок в новом выражении

Рассмотрим эту программу:

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, но не нашел ничего подходящего.


comment
{0} часто вводит в заблуждение, так как это означает инициализацию нуля первого элемента и инициализацию значения остальных. Лучше просто использовать {} или () для инициализации значения всего объекта (это установит его в 0). Кстати, это тоже нормально компилируется на gcc.   -  person rustyx    schedule 29.09.2019


Ответы (1)


Да, это определенно ошибка. new выражения определены для использования правил прямой инициализации ([expr. new] /18.2), а исключение скобок применяется ко всем случаям агрегированной инициализации ([dcl.init.aggr] / 12).

Сообщите об ошибке, если не можете найти ее после поиска в bugzilla.

person L. F.    schedule 29.09.2019