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

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

本文关键字:数组 对象 是什么 方法 二维 声明 c++ 初始化 大型      更新时间:2023-10-16

我需要创建一个大的二维对象数组。我在这个网站上读过一些相关的问题,其他关于multi_array,矩阵,矢量等,但还没有能够把它放在一起。如果您推荐使用其中之一,请继续翻译下面的代码。

一些注意事项:

  • 数组有点大(1300 x 1372)。
  • 我可能在同一时间使用不止一个。
  • 我必须在某个时候把它传递给一个函数。
  • 速度是一个大因素。

我想到的两种方法是:

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

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);
        ...
    }
}

这里正确的方法/语法是什么?

编辑:

几个答案都假设Pixel很小——为了方便,我省略了Pixel的细节,但它并不小/微不足道。它有大约20个数据成员和大约16个成员函数。

您的第一种方法在堆栈上分配所有内容,这在其他方面很好,但是当您试图分配过多的堆栈时,会导致堆栈溢出。在现代操作系统上,限制通常在8兆字节左右,因此在堆栈上分配1300 * 1372个元素的数组是不可能的。

第二种方法在堆上分配1300 * 1372个元素,这对分配器来说是一个巨大的负载,分配器将多个链表保存到已分配和空闲内存块中。这也是一个坏主意,尤其是Pixel看起来相当小。

我要做的是:

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);
        ...
    }
}

这种方式可以在堆上分配一大块内存。

如果你想把它传递给一个函数,我反对使用简单数组。考虑:

void doWork(Pixel array[][]);

不包含任何大小信息。您可以通过单独的参数传递大小信息,但我宁愿使用类似std::vector的东西。当然,这需要您定义一个寻址约定(行为主或列为主)。

可以选择std::vector,其中每一层向量是一个数组维。优点:像pixelArray[x][y]这样的双下标可以工作,但是创建这样的结构体很繁琐,复制成本更高,因为它发生在每个包含的vector实例中,而不是简单的memcpy中,并且顶层vector中包含的vector不一定具有相同的大小。

这些基本上是您使用标准库的选项。正确的解决方案应该是类似于二维的std::vector。我们会想到数值库和图像处理库,但是矩阵类和图像类很可能被限制为元素中的基本数据类型。

编辑:忘了说明上面的所有内容都只是参数。最后,你的个人品味和语境也要考虑进去。如果你是一个人在项目中,向量加上定义和文档的寻址约定应该是足够好的。但是,如果您是在一个团队中,并且很可能有人会忽略文档约定,那么级联向量中向量结构可能更好,因为繁琐的部分可以通过辅助函数实现。

我不确定你的Pixel数据类型有多复杂,但也许这样的东西会为你工作?:

std::fill(array, array+ 100,42);//设置数组中的每个值为42

参考:初始化具有一个默认值的普通数组

查看Boost的通用图像库。

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

我个人倾向于使用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

虽然我不一定要让它成为一个结构体,但这演示了我将如何存储和访问数据。如果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;
};