假设我在类中定义了一个平方网格:
Square (* grid)[];
奇怪的是,这似乎编译得很好。我认为它会出错,因为编译器不知道数组有多大?
无论如何,
这意味着它是一个指向数组的指针。然后初始化它,我做:
grid(new Square[width * height])
编译器不接受这一点,因为new
语句返回指向正方形的指针而不是指向正方形数组的指针。这样做是有意义的。现在,有没有一种简单的方法来完成我的要求,除了声明Square ** grid
并循环遍历它并为2D数组的每一列进行单独的分配?
答案 0 :(得分:3)
Square (* grid)[];
奇怪的是,这似乎编译得很好。我认为它会出错,因为编译器不知道数组有多大?
那是声明指向数组的指针,而不是数组;可以声明指向任何不完整类型的指针,包括未知大小的数组。但是,这是一件非常不寻常的事情,而不是你想要的动态数组。
现在,有一种简单的方法可以完成我的要求吗?
最简单的动态数组是:
std::vector<Square> grid;
初始化为
grid(width * height)
如果您真的想自己管理内存,那么将指向数组的指针更改为指向对象的指针:
Square * grid;
初始化为
grid(new Square[width * height])
指针可以指向单个对象,也可以指向数组的开头;如果它确实指向一个数组,那么就可以像使用非动态数组一样使用[]
。确保在完成后将其解除分配(delete [] grid;
)。
如果你想要一个二维数组,通常最容易使用一维数组,并在访问器函数中包含必要的算术:
Square & get_square(size_t row, size_t col) {
return grid[row * width + col];
}
答案 1 :(得分:0)
我认为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
个参数(而对于原始数组,数组语法只是成为指针的同义词),函数可以返回{{1}然而,它们被莫名其妙地禁止返回数组(语法为std::array
),而int foo()[3];
则不需要特殊的数组分配器std::array
,它必须与数组deallocator {匹配} { {1}}(相反,您可以说new[]
然后'删除foo;')