#include <stdlib.h>
void *operator new[](size_t size, int n){
if( size != 0 && n != 0 )
return calloc(n, size);
return calloc(1, 1);
}
int main(){
int * p1;
const int i = 0;
// p1 = new (20) int[i] ; // Case 1 (OK)
p1 = new (20) (int[i]); // Case 2 (Warning)
if( p1 == 0 )
return 1;
return 0;
}
Этот код (https://godbolt.org/g/hjo7Xn) успешно компилируется с Clang 6.0.0, однако GCC 7.3 выдает предупреждение о том, что массивы нулевой длины запрещены в C++. Если скобки удалены (случай 1), предупреждение исчезает.
В отличие от статически распределенных массивов нулевой длины (C++ 03: 8.3.4/1) допускаются динамически распределенные массивы нулевой длины (C++ 03: 5.3.4/6). Тем не менее, в стандарте C++ последние явно разрешены только при выполнении одного из двух возможных путей синтаксиса нового выражения, то есть с идентификатором нового типа и без круглых скобок (случай 1).
Разрешено ли стандартом C++ использовать новое выражение с массивом нулевой длины после второго пути синтаксиса, то есть с идентификатором типа и круглыми скобками (случай 2)?
Единственная связанная цитата - C++ 03: 5.3.4/5:
Когда выделенным объектом является массив (т.е. Используется синтаксис direct-new-declarator или идентификатор нового типа или идентификатор типа обозначает тип массива), новое выражение дает указатель на исходный элемент (если любой) массива.
Однако формулировка (if any)
допускает массив без элементов, однако не ясно, относится ли оно к обоим случаям или относится только к идентификатору нового типа и без круглых скобок (случай 1).
Заранее спасибо.
Заметки:
- ISO/IEC 14882: 2003, раздел 8.3.4, пункт 1:
Если присутствует постоянное выражение (5.19), оно должно быть интегральным постоянным выражением, и его значение должно быть больше нуля.
- ISO/IEC 14882: 2003, раздел 5.3.4, абзац 6:
Выражение в direct-new-declarator должно иметь интегральный или перечисляемый тип (3.9.1) с неотрицательным значением.
- ISO/IEC 14882: 2003, раздел 5.3.4, пункт 7:
Когда значение выражения в direct-new-declarator равно нулю, функция распределения вызывается для выделения массива без элементов.
- ISO/IEC 14882: 2003, раздел 5.3.4, пункт 1:
новое выражение:
::
opt
new new-placementopt
new-type-id new-initializeropt
::
opt
new new-placementopt
(type-id) new-initializeropt
- Хотя приведенные выше цитаты из стандарта C++ 03, насколько мне известно, эта проблема все еще неясно в новых версиях стандарта C++ (C++ 11, C++ 14 и C++ 17).
- Интересный Herb Sutter сообщение о нулевой длины массивов.
- Код в этом примере представляет собой слегка измененный тест из пакета SuperTest от SolidSands.