我想找到在C++中实现三维整数数组的安全方法,使用指针算术/动态内存分配,或者使用STL
矢量等技术.
基本上我希望我的整数数组维度看起来像:
[ x ][ y ][ z ]
x和y在20-6000范围内是已知的并且等于4.
看看Boost 多维数组库.这是一个例子(改编自Boost文档):
#include "boost/multi_array.hpp" int main() { // Create a 3D array that is 20 x 30 x 4 int x = 20; int y = 30; int z = 4; typedef boost::multi_arrayarray_type; typedef array_type::index index; array_type my_array(boost::extents[x][y][z]); // Assign values to the elements int values = 0; for (index i = 0; i != x; ++i) { for (index j = 0; j != y; ++j) { for (index k = 0; k != z; ++k) { my_array[i][j][k] = values++; } } } }
每对方括号都是一个解除引用操作(当应用于指针时).例如,以下几行代码是等效的:
x = myArray[4]; x = *(myArray+4);
x = myArray[2][7]; x = *((*(myArray+2))+7);
要使用建议的语法,您只需取消引用第一个取消引用返回的值.
int*** myArray = (some allocation method, keep reading); // // All in one line: int value = myArray[x][y][z]; // // Separated to multiple steps: int** deref1 = myArray[x]; int* deref2 = deref1[y]; int value = deref2[z];
要分配这个数组,你只需要认识到你实际上没有一个三维的整数数组.你有一个整数数组数组.
// Start by allocating an array for array of arrays int*** myArray = new int**[X_MAXIMUM]; // Allocate an array for each element of the first array for(int x = 0; x < X_MAXIMUM; ++x) { myArray[x] = new int*[Y_MAXIMUM]; // Allocate an array of integers for each element of this array for(int y = 0; y < Y_MAXIMUM; ++y) { myArray[x][y] = new int[Z_MAXIMUM]; // Specify an initial value (if desired) for(int z = 0; z < Z_MAXIMUM; ++z) { myArray[x][y][z] = -1; } } }
取消分配此数组遵循类似的过程来分配它:
for(int x = 0; x < X_MAXIMUM; ++x) { for(int y = 0; y < Y_MAXIMUM; ++y) { delete[] myArray[x][y]; } delete[] myArray[x]; } delete[] myArray;
下面是在每个阵列的一个内存块中使用C或C++创建3D数组的简单方法.不需要使用BOOST(即使它很好),或者在具有多个间接的行之间拆分分配(这是非常糟糕的,因为它通常在访问数据时会给性能带来很大的损失并且会破坏内存).
唯一要理解的是没有多维数组,只有数组(数组).最里面的索引是记忆中最远的.
#include#include int main(){ { // C Style Static 3D Arrays int a[10][20][30]; a[9][19][29] = 10; printf("a[9][19][29]=%d\n", a[9][19][29]); } { // C Style dynamic 3D Arrays int (*a)[20][30]; a = (int (*)[20][30])malloc(10*20*30*sizeof(int)); a[9][19][29] = 10; printf("a[9][19][29]=%d\n", a[9][19][29]); free(a); } { // C++ Style dynamic 3D Arrays int (*a)[20][30]; a = new int[10][20][30]; a[9][19][29] = 10; printf("a[9][19][29]=%d\n", a[9][19][29]); delete [] a; } }
对于您的实际问题,由于可能存在两个未知维度,因此我的提案存在问题,只允许一个未知维度.有几种方法可以解决这个问题.
好消息是使用变量现在可以使用C,它被称为可变长度数组.你看这里的细节.
int x = 100; int y = 200; int z = 30; { // C Style Static 3D Arrays int a[x][y][z]; a[99][199][29] = 10; printf("a[99][199][29]=%d\n", a[99][199][29]); } { // C Style dynamic 3D Arrays int (*a)[y][z]; a = (int (*)[y][z])malloc(x*y*z*sizeof(int)); a[99][199][29] = 10; printf("a[99][199][29]=%d\n", a[99][199][29]); free(a); }
如果使用C++,最简单的方法可能是使用运算符重载来坚持数组语法:
{ class ThreeDArray { class InnerTwoDArray { int * data; size_t y; size_t z; public: InnerTwoDArray(int * data, size_t y, size_t z) : data(data), y(y), z(z) {} public: int * operator [](size_t y){ return data + y*z; } }; int * data; size_t x; size_t y; size_t z; public: ThreeDArray(size_t x, size_t y, size_t z) : x(x), y(y), z(z) { data = (int*)malloc(x*y*z*sizeof data); } ~ThreeDArray(){ free(data); } InnerTwoDArray operator [](size_t x){ return InnerTwoDArray(data + x*y*z, y, z); } }; ThreeDArray a(x, y, z); a[99][199][29] = 10; printf("a[99][199][29]=%d\n", a[99][199][29]); }
上面的代码有一些用于访问InnerTwoDArray的间接成本(但是一个好的编译器可能可以优化它)但是在堆上分配的数组只使用一个内存块.这通常是最有效的选择.
显然,即使上面的代码仍然简单明了,STL或BOOST做得很好,因此无需重新发明轮子.我仍然相信知道它可以轻松完成是有趣的.