在 c++ 中声明和初始化(大型)二维对象数组的正确方法是什么?
What's the proper way to declare and initialize a (large) two dimensional object array in c++?
我需要创建一个大的二维对象数组。我在这个网站上读过一些相关的问题,其他关于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
这些基本上是您使用标准库的选项。正确的解决方案应该是类似于二维的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;
};
- 销毁C++中动态分配的内存(数组对象)
- 数组对象的生存期是否在重用其元素存储时结束?
- 为什么顶点数组对象会导致错误?
- 具有纯虚函数和指针数组对象类型的父类的指针数组
- 这是使用构造函数初始化数组对象的最佳方法吗?
- OpenGL 顶点数组对象与 tinyobjloader
- 将数组/对象/结构列表从C#库中传递给C MFC应用程序
- C++ RapidJson 帮助反序列化数组对象
- ptrdiff_t可以表示指向同一数组对象元素的指针的所有减法吗?
- 检查成员函数是否返回临时对象或数组对象
- 为什么 std::variant 不能容纳数组对象类型,而联合可以?
- 当数组对象以函数参数传递时,为什么复制构造函数会自称
- 如何使用箭头指针打印出一类数组对象,这些对象中有多个分数
- C++17 std::shared_ptr<> 类数组对象的重载运算符 []
- 添加两个具有运算符重载的数组对象,从而导致分段错误
- opengl:两个不同的矢量可以绑定到同一个顶点数组对象吗
- 使用相同的数据填充数组对象或使用指针
- 方法用于最快的分配,并且不需要将动态大小的数组对象作为局部变量
- 如何将2d数组对象传递给c++中的函数
- ReferenceTable溢出(jni-android),数组对象释放