简体   繁体   English

在C ++中声明和初始化(大)二维对象数组的正确方法是什么?

[英]What's the proper way to declare and initialize a (large) two dimensional object array in c++?

I need to create a large two dimensional array of objects. 我需要创建一个大型的二维对象数组。 I've read some related questions on this site and others regarding multi_array, matrix, vector, etc, but haven't been able to put it together. 我已经阅读了本网站上的一些相关问题,以及有关multi_array,矩阵,向量等的其他问题,但尚未将它们放在一起。 If you recommend using one of those, please go ahead and translate the code below. 如果您建议使用其中之一,请继续翻译下面的代码。

Some considerations: 一些注意事项:

  • The array is somewhat large (1300 x 1372). 阵列有些大(1300 x 1372)。
  • I might be working with more than one of these at a time. 我可能一次要处理其中一个以上的问题。
  • I'll have to pass it to a function at some point. 我必须在某个时候将其传递给函数。
  • Speed is a large factor. 速度是一个很大的因素。

The two approaches that I thought of were: 我想到的两种方法是:

Pixel pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i][j].setOn(true);
        ...
    }
}

and

Pixel* pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i][j] = new Pixel();
        pixelArray[i][j]->setOn(true);
        ...
    }
}

What's the right approach/syntax here? 什么是正确的方法/语法?

Edit: 编辑:

Several answers have assumed Pixel is small - I left out details about Pixel for convenience, but it's not small/trivial. 几个答案都假定Pixel很小-为了方便起见,我省略了有关Pixel详细信息,但这并不是很小的。 It has ~20 data members and ~16 member functions. 它具有〜20个数据成员和〜16个成员函数。

Your first approach allocates everything on stack, which is otherwise fine, but leads to stack overflow when you try to allocate too much stack. 您的第一种方法是在堆栈上分配所有内容,否则可以这样做,但是当您尝试分配过多的堆栈时会导致堆栈溢出。 The limit is usually around 8 megabytes on modern OSes, so that allocating arrays of 1300 * 1372 elements on stack is not an option. 在现代操作系统上,限制通常为8兆字节左右,因此不能选择在堆栈上分配1300 * 1372个元素的数组。

Your second approach allocates 1300 * 1372 elements on heap, which is a tremendous load for the allocator, which holds multiple linked lists to chunks of allocted and free memory. 第二种方法是在堆上分配1300 * 1372个元素,这对于分配器来说是巨大的负担,该分配器将多个链接列表保存到已分配和可用内存的块中。 Also a bad idea, especially since Pixel seems to be rather small. 这也是一个坏主意,尤其是因为Pixel看起来很小。

What I would do is this: 我要做的是:

Pixel* pixelArray = new Pixel[1300 * 1372];
for(int i=0; i<1300; i++) {
    for(int j=0; j<1372; j++) {
        pixelArray[i * 1372 + j].setOn(true);
        ...
    }
}

This way you allocate one large chunk of memory on heap. 这样,您可以在堆上分配一大块内存。 Stack is happy and so is the heap allocator. 堆栈很高兴,堆分配器也很高兴。

If you want to pass it to a function, I'd vote against using simple arrays. 如果您想将其传递给函数,我反对使用简单数组。 Consider: 考虑:

void doWork(Pixel array[][]);

This does not contain any size information. 它不包含任何尺寸信息。 You could pass the size info via separate arguments, but I'd rather use something like std::vector<Pixel>. 您可以通过单独的参数传递大小信息,但是我宁愿使用类似std :: vector <Pixel>的名称。 Of course, this requires that you define an addressing convention (row-major or column-major). 当然,这要求您定义一个寻址约定(行优先或列主要)。

An alternative is std::vector<std::vector<Pixel> >, where each level of vectors is one array dimension. 另一种选择是std :: vector <std :: vector <Pixel>>,其中向量的每一级都是一个数组维。 Advantage: The double subscript like in pixelArray[x][y] works, but the creation of such a structure is tedious, copying is more expensive because it happens per contained vector instance instead of with a simple memcpy, and the vectors contained in the top-level vector must not necessarily have the same size. 优点:像pixelArray [x] [y]中的双下标一样有效,但是创建这种结构很繁琐,复制更加昂贵,因为它是针对每个包含的向量实例而不是简单的memcpy进行的,并且包含在向量中的向量顶层向量不一定必须具有相同的大小。

These are basically your options using the Standard Library. 这些基本上是使用标准库的选项。 The right solution would be something like std::vector with two dimensions. 正确的解决方案是带有二维的std :: vector之类的东西。 Numerical libraries and image manipulation libraries come to mind, but matrix and image classes are most likely limited to primitive data types in their elements. 想到了数字库和图像处理库,但是矩阵和图像类很可能仅限于其元素中的原始数据类型。

EDIT: Forgot to make it clear that everything above is only arguments. 编辑:忘了清楚地说,以上所有内容仅是参数。 In the end, your personal taste and the context will have to be taken into account. 最后,必须考虑您的个人品味和环境。 If you're on your own in the project, vector plus defined and documented addressing convention should be good enough. 如果您一个人在项目中,vector加上定义和记录的寻址约定应该就足够了。 But if you're in a team, and it's likely that someone will disregard the documented convention, the cascaded vector-in-vector structure is probably better because the tedious parts can be implemented by helper functions. 但是,如果您在一个团队中,并且很可能有人会无视已记录在案的约定,那么级联的向量中向量结构可能会更好,因为繁琐的部分可以通过辅助函数来实现。

I'm not sure how complicated your Pixel data type is, but maybe something like this will work for you?: 我不确定您的Pixel数据类型有多复杂,但也许这样的方法对您有用吗?:

std::fill(array, array+100, 42); std :: fill(array,array + 100,42); // sets every value in the array to 42 //将数组中的每个值设置为42

Reference: Initialization of a normal array with one default value 参考: 使用一个默认值初始化普通数组

Check out Boost's Generic Image Library. 查看Boost的通用图像库。

gray8_image_t pixelArray;
pixelArray.recreate(1300,1372);
for(gray8_image_t::iterator pIt = pixelArray.begin(); pIt != pixelArray.end(); pIt++) {
    *pIt = 1;
}

While I wouldn't necessarily make this a struct, this demonstrates how I would approach storing and accessing the data. 虽然我不一定要使它成为一个结构,但这说明了我将如何存储和访问数据。 If Pixel is rather large, you may want to use a std::deque instead. 如果Pixel很大,则可能要改用std :: deque。

struct Pixel2D {
  Pixel2D (size_t rsz_, size_t csz_) : data(rsz_*csz_), rsz(rsz_), csz(csz_) {
    for (size_t r = 0; r < rsz; r++)
    for (size_t c = 0; c < csz; c++)
      at(r, c).setOn(true);
  }
  Pixel &at(size_t row, size_t col) {return data.at(row*csz+col);}
  std::vector<Pixel> data;
  size_t rsz;
  size_t csz;
};

My personal peference would be to use std::vector 我个人的看法是使用std :: vector

typedef  std::vector<Pixel>       PixelRow;
typedef  std::vector<PixelRow>    PixelMatrix;

PixelMatrix   pixelArray(1300, PixelRow(1372, Pixel(true)));
      //                 ^^^^           ^^^^  ^^^^^^^^^^^
      //                 Size 1         Size 2   default Value

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM