Я считаю, что причина Square (* grid)[];
в том, что указатели на неполные типы разрешены, а массив без размера считается неполным типом.
Причина, по которой вы не можете сделать
Square (* grid)[] = new Square[width * height];
даже если кажется, что типы идеально совпадают, это просто еще одно проявление ошибки в дизайне C, когда типы массивов обрабатываются специально. Кажется, что new
объект типа Square[]
должен возвращать указатель на объект этого типа. Однако вы на самом деле не new
используете тип массива, но new[]
используете тип элемента Square
. Результатом new[]
является указатель на тип элемента в соответствии с соглашением C для массивов.
Вы можете использовать приведение, чтобы исправить это, чтобы использовать правильный тип:
// pretend array types behave rationally
Square (* grid)[] = (Square (*)[]) new Square[width * height];
(*grid)[3] = 10;
// the above is equivalent to the following
Square *grid = new Square[width * height];
grid[3] = 10;
Или вы можете просто сделать это C ++ и использовать std::vector
std::vector<Square> grid(width * height);
Если у вас есть массив фиксированного размера, вы можете использовать std::array
std::array<Square,10> *grid = new std::array<Square,10>;
std::array
в значительной степени исправляет все ошибки, допущенные при проектировании типов массивов. Например, std::array
не может «забыть» свой размер, функции могут принимать std::array
параметров по значению (тогда как с необработанными массивами синтаксис массива просто становится синонимом для указателей), функции могут возвращать std::array
, тогда как они необъяснимо запрещены. от возврата массивов (синтаксис будет int foo()[3];
), а с std::array
нет необходимости в специальном распределителе массива new[]
, который должен быть сопоставлен с освобождающим массивом delete[]
(вместо этого вы можете сказать foo = new std::array<int,3>
, а затем 'delete foo;')