如何在 C++ 中解决非常大的二维数组
我需要创建一个大小为 800x800 的 2D int 数组。 但这样做会造成堆栈溢出(哈哈)。
我是 C++ 新手,所以我应该做一些类似于向量的向量的事情吗? 然后将二维数组封装到一个类中?
具体来说,这个数组是我在图形程序中的 zbuffer。 我需要存储屏幕上每个像素的 az 值(因此尺寸为 800x800)。
谢谢!
I need to create a 2D int array of size 800x800. But doing so creates a stack overflow (ha ha).
I'm new to C++, so should I do something like a vector of vectors? And just encapsulate the 2d array into a class?
Specifically, this array is my zbuffer in a graphics program. I need to store a z value for every pixel on the screen (hence the large size of 800x800).
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我可能会创建一个 800*800 的一维数组。 使用像这样的单个分配可能比分配 800 个单独的向量更有效。
然后,可能将其封装在一个类似于二维数组的类中。
这里显示的抽象有很多漏洞,例如,如果您访问“行”末尾之后会发生什么? 《Effective C++》一书对用 C++ 编写良好的多维数组进行了很好的讨论。
I might create a single dimension array of 800*800. It is probably more efficient to use a single allocation like this, rather than allocating 800 separate vectors.
Then, probably encapsulate that in a class that acted like a 2D array.
The abstraction shown here has a lot of holes, e.g, what happens if you access out past the end of a "row"? The book "Effective C++" has a pretty good discussion of writing good multi dimensional arrays in C++.
你可以做一个向量的向量,但这会产生一些开销。 对于 z 缓冲区,更典型的方法是创建一个大小为 800*800=640000 的数组。
然后按如下方式访问像素:
You could do a vector of vectors, but that would have some overhead. For a z-buffer the more typical method would be to create an array of size 800*800=640000.
Then access the pixels as follows:
好吧,在 Niall Ryan 的基础上,如果性能是一个问题,您可以通过优化数学并将其封装到一个类中来更进一步。
所以我们将从一些数学开始。 回想一下,800 可以写成 2 的幂:
因此,我们可以将寻址函数写为:
因此,如果我们将所有内容封装到一个漂亮的类中,我们会得到:
Well, building on what Niall Ryan started, if performance is an issue, you can take this one step further by optimizing the math and encapsulating this into a class.
So we'll start with a bit of math. Recall that 800 can be written in powers of 2 as:
So we can write our addressing function as:
So if we encapsulate everything into a nice class we get:
如果您只需要一个实例,您可以在静态存储上分配数组(在文件范围内,或在函数范围内添加
static
限定符)。这样它就不会进入堆栈,并且您不必处理动态内存。
You can allocate array on static storage (in file's scope, or add
static
qualifier in function scope), if you need only one instance.This way it will not go to the stack, and you not have to deal with dynamic memory.
您需要大约 2.5 兆,因此仅使用堆就可以了。 除非需要调整矢量大小,否则不需要矢量。 有关使用“2D”堆的示例,请参阅 C++ FAQ Lite大批。
(完成后,不要忘记
删除[]
它。)You need about 2.5 megs, so just using the heap should be fine. You don't need a vector unless you need to resize it. See C++ FAQ Lite for an example of using a "2D" heap array.
(Don't forget to
delete[]
it when you're done.)到目前为止,每一篇文章都将内存管理留给了程序员。 这是可以而且应该避免的。 ReaperUnreal 与我所做的非常接近,除了我使用向量而不是数组,并且还制作维度模板参数并更改访问函数 - 哦,只是 IMNSHO 清理一下:
现在你可以分配堆栈上的这个二维数组很好:
我希望这有帮助!
编辑:从 Array2D::buffer 中删除了数组规范。 感谢安德烈亚斯抓住了这一点!
Every post so far leaves the memory management for the programmer. This can and should be avoided. ReaperUnreal is darn close to what I'd do, except I'd use a vector rather than an array and also make the dimensions template parameters and change the access functions -- and oh just IMNSHO clean things up a bit:
Now you can allocate this 2-D array on the stack just fine:
I hope this helps!
EDIT: Removed array specification from
Array2D::buffer
. Thanks to Andreas for catching that!您可以做的一件事是使用 VC 更改堆栈大小(如果您确实想要堆栈上的数组),执行此操作的标志是 [/F](http://msdn.microsoft.com/en-us/library/tdkhxaks(VS.80).aspx)。
但您可能想要的解决方案是将内存放在堆中而不是堆栈中,因为您应该使用
向量
的向量
。下面一行声明了一个包含 800 个元素的向量,每个元素都是一个包含 800 个 int 的向量,从而使您无需手动管理内存。
请注意两个右尖括号 (
> >
) 之间的空格,这是为了消除它与右移运算符的歧义(在 C++0x)。One thing you can do is change the stack size (if you really want the array on the stack) with VC the flag to do this is [/F](http://msdn.microsoft.com/en-us/library/tdkhxaks(VS.80).aspx).
But the solution you probably want is to put the memory in the heap rather than on the stack, for that you should use a
vector
ofvectors
.The following line declares a
vector
of 800 elements, each element is avector
of 800int
s and saves you from managing the memory manually.Note the space between the two closing angle brackets (
> >
) which is required in order disambiguate it from the shift right operator (which will no longer be needed in C++0x).不过,凯文的例子很好:
应该
稍微扩展一下,您当然可以添加运算符重载而不是 at() 函数:
和
示例:
Kevin's example is good, however:
Should be
Expanding it a bit you could of course add operator-overloads instead of the at()-functions:
and
Example:
有一种类似 C 的做法:
您可以使用简单的 get 和 set 方法将 y * xwidth + x 封装在类中(可能会重载
[]
运算符 if您想开始学习更高级的 C++)。 如果您刚刚开始使用 C++ 并且没有开始为 n 维数组创建可重用的完整类模板,我建议您慢慢地进行此操作,这只会让您在开始时感到困惑。一旦您开始图形工作,您可能会发现额外的类调用的开销可能会减慢您的代码。 不过,不必担心这一点,除非您的应用程序速度不够快,并且您可以对其进行分析以显示时间损失的位置,而不是使其在开始时更加难以使用并可能造成不必要的复杂性。
我发现 C++ lite FAQ 非常适合提供此类信息。 特别是您的问题的答案是:
http:// www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.16
There's the C like way of doing:
You could encapsulate the
y * xwidth + x
inside a class with an easy get and set method (possibly with overloading the[]
operator if you want to start getting into more advanced C++). I'd recommend getting to this slowly though if you're just starting with C++ and not start creating re-usable fully class templates for n-dimension arrays which will just confuse you when you're starting off.As soon as you get into graphics work you might find that the overhead of having extra class calls might slow down your code. However don't worry about this until your application isn't fast enough and you can profile it to show where the time is lost, rather than making it more difficult to use at the start with possible unnecessary complexity.
I found that the C++ lite FAQ was great for information such as this. In particular your question is answered by:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.16
或者你可以尝试这样的事情:
你应该仍然能够这样做:
不再担心管理内存,没有自定义类需要照顾,而且很容易扔掉。
Or you could try something like:
You should still be able to do this too:
No more worries about managing the memory, no custom classes to take care of, and it's easy to throw around.