指向动态数组的指针

发布于 2025-01-03 15:05:39 字数 342 浏览 1 评论 0原文

假设我在类中定义了一个平方网格:

Square (* grid)[];

奇怪的是,这似乎编译得很好。我认为它会出错,因为编译器不知道数组有多大? 无论如何, 这意味着它是一个指向数组的指针。然后为了初始化它,我这样做:

grid(new Square[width * height])

编译器不接受这一点,因为 new 语句返回一个指向正方形的指针,而不是指向正方形数组的指针。这样做是有道理的。现在,除了声明 Square ** grid 并循环遍历它并为 2D 数组的每一列进行单独分配之外,还有一种简单的方法可以完成我的要求吗?

Suppose I have a grid of squared defined like so in a class:

Square (* grid)[];

This, oddly, seems to compile fine. I would think it would error because the compiler doesn't know how big the array is?
Anyways,
it means it is a pointer to an array. Then to initialize it, I do:

grid(new Square[width * height])

This isn't accepted by the compiler, because the new statement returns a pointer to squares rather than a pointer to an array of squares. It makes sense that it does that. Now, is there a simple way to accomplish what I'm asking, other than just declaring Square ** grid and looping through it and doing separate allocations for each column of the 2D array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的影子我的梦 2025-01-10 15:05:39
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];
}
Square (* grid)[];

This, oddly, seems to compile fine. I would think it would error because the compiler doesn't know how big the array is?

That's declaring a pointer to an array, not an array; it's fine to declare a pointer to any incomplete type, including an array of unknown size. However, it's quite an unusual thing to do, and not what you want for a dynamic array.

Now, is there a simple way to accomplish what I'm asking?

The easiest dynamic array to use is:

std::vector<Square> grid;

initialised as

grid(width * height)

If you really want to manage the memory yourself, then change your pointer-to-array to a pointer-to-object:

Square * grid;

initialised as

grid(new Square[width * height])

A pointer can point to either a single object, or the start of an array; if it does point to an array, then you can use [] on it just like with a non-dynamic array. Make sure you deallocate it (delete [] grid;) once you've finished with it.

If you want a 2-dimensional array, it's often easiest to use a 1-dimensional array, and wrap the necessary arithmetic in an accessor function:

Square & get_square(size_t row, size_t col) {
    return grid[row * width + col];
}
攀登最高峰 2025-01-10 15:05:39

我相信 Square (* grid)[]; 起作用的原因是允许指向不完整类型的指针,并且没有大小的数组被视为不完整类型。

尽管看起来类型完美匹配却无法做到这一点,

Square (* grid)[] = new Square[width * height];

这只是 C 设计中对数组类型进行特殊处理的错误的另一个表现。看起来 new 类型 Square[] 的对象应该返回一个指向该类型对象的指针。然而,您并不是真正new数组类型,而是new[]元素类型Squarenew[] 的结果是指向元素类型的指针,符合数组的 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 然后“删除 foo;”)

I believe the reason Square (* grid)[]; works is because pointers to incomplete types are allowed, and an array without a size counts as an incomplete type.

The reason that you can't do

Square (* grid)[] = new Square[width * height];

even though it looks like the types match up perfectly is just another manifestation of the bug in the design of C where array types are treated specially. It seems like newing an object of type Square[] should return a pointer to an object of that type. However you're not really newing an array type, but new[]ing the element type Square. The result of new[] is a pointer to the element type, in line with the C convention for arrays.

You can use a cast to 'fix' this to use the 'right' type:

// 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;  

Or you can just do it the C++ way and use a std::vector

std::vector<Square> grid(width * height);

If you have a fixed size array you can use std::array

std::array<Square,10> *grid = new std::array<Square,10>;

std::array pretty much fixes all the mistakes made in the design of array types. For example std::array can't 'forget' its size, functions can take std::array parameters by value (whereas with raw arrays the array syntax just becomes a synonym for pointers), functions can return std::array whereas they are inexplicably prohibited from returning arrays (The syntax would be int foo()[3];), and with std::array there's no need for a special array allocator new[] which must be matched to an array deallocator delete[] (instead you can say foo = new std::array<int,3> and then 'delete foo;')

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文