2008-12-04 36 views

回答

24

如果知道嵌套尺寸的大小已经,也可以使用从字面上新分配一个多维数组:

typedef int dimensions[3][4]; 

dimensions * dim = new dimensions[10]; 
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42; 
delete [] dim; 

代替10,运行时确定的值可以被传递。由于它不是类型运算符新的回报的一部分,这是允许的。例如,如果您知道列的数量,但希望保持行数变化,这很好。 typedef使读取代码更容易。

+0

不删除[] [] []昏暗? ;-) – 2008-12-04 15:34:22

+3

这个答案是种讨厌的:http://stackoverflow.com/questions/198051/why-delete-multidimensionalarray-operator-in-c-does-not-exist#326338,但希望回答您的问题:) – 2008-12-04 15:58:57

+0

不错的一个,litb。我不知道你能做到这一点。 – 2008-12-04 16:42:33

3

这是我得到的实现;我声明了一个连续的int块,而不是在我的for循环中创建新块,所以我不会在整个地方导致页面错误。感谢eJames指出为什么这段代码最初被破坏了。

int width = 10, height = 10, totalSize = width*height; 
int **myArray = new int*[width]; 
int *data = new int[totalSize]; 

for (int i = 0; i < height; ++i) 
{ 
    myArray[i] = data + (i*width); 
} 

// do some things here 

delete[] data; 
delete[] myArray; 
+0

此代码将不会如图所示工作。具体来说,在你的循环中写入myArray [i]将会遍布整个地方。看到我的修改循环这里:http://stackoverflow.com/questions/340943/c-multi-dimensional-arrays-on-the-heap#341008 – 2008-12-04 16:45:05

2

您的循环不会正确地将指针值写入myArray。我建议不要使用以下:

int width = 10; 
int height = 10; 
int ** myArray = new int*[width]; 
int * data = new int[width*height]; 
int * index = data; 
for (int i = 0; i < width; i++) 
{ 
    myArray[i] = index; 
    index += height; 
} 

// ... 

delete[] data; 
delete[] myArray;
+0

你是对的;我有这个工作,并重构它没有检查它是否工作。也许我应该停止打破构建... – eplawless 2008-12-04 16:54:39

6

看到这个:“我如何使用新的分配多维数组” C++ FAQ by Marshall Cline

见和“但是,以前的FAQ的代码是SOOOO棘手和容易出错!是不是有一个更简单的方法?”部分。

3

std::vector<std::vector<int> >应该被提及,因为它通常是最简单的方法。但是,请注意它不是矩形。并非每个std::vector<int>都需要具有相同的长度。

6

为了完整起见,当您知道数组边界时,这里有一个更好的方法可以在C++中完成。使用以下类的好处是,您不必关心在数据上调用delete []。这意味着这个类将是异常安全的,以及其他所有关于RAII的好东西。

template<typename T, int width, int height> 
class MultiArray 
{ 
    private: 
     typedef T cols[height]; 
     cols * data; 
    public: 
     T& operator() (int x, int y) { return data[x][y]; } 
     MultiArray() { data = new cols[width]; } 
     ~MultiArray() { delete [] data; } 
};

用法:

MultiArray<int, 10, 10> myArray; 
myArray(2, 3) = 4; 
cout << myArray(2, 3);

编辑:和,而我在这,这里是设置你可以使用,如果你知道数组边界,直到运行时:

template<typename T> 
class Array2D 
{ 
    private: 
     const int width; 
     T * data; 
    public: 
     T& operator() (int x, int y) { return data[y*width + x]; } 
     Array2D(const int w, const int h) : width(w) { data = new T[w*h]; } 
     ~Array2D() { delete [] data; } 
};

用法:

Array2D myArray(10, 10); 
myArray(3, 4) = 42; 
cout << myArray(3, 4);
0

如果您只是将正确数量的元素放在一起,您可以将一维索引为2,3或N维。例如,如果我有10行和10列,我知道如果我在第3行,我将不得不经过至少30个元素才能到达它。

不知何故,我更喜欢简单二维数组的这种表示法,因为我不需要担心嵌套的指针级别。缺点是索引符号更加混乱。下面是一个二维数组具有n行和m列的例子:

int *matrix = new int[n*m]; 

//set element (3,7) to 10 
matrix[3*m+7] = 10; 

//print the matrix 
for (int i = 0; i < n; i++) { 
    for (int j = 0; j < m; j++) { 
    cout << matrix[i*m+j] << ' '; 
    } 
    cout << '\n'; 
} 
3

我很惊讶没有人提到boost::multi_array呢。上个星期我在一个程序中需要一个二维数组,并且发现它比我之前提出的家庭酿造解决方案更容易,更快速地编写代码(所有这些都在其他评论中提到过) 。

0

我的问题here涵盖几乎相同的话题比较好感谢一些高超的答案。但是,它不包括N维数组,我在这里的答案中也没有看到这些数组,但这会很有用。

6

如何使用Boost.MultiArray的?我相信它很好地满足你的需求! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction

这里是从文档页面的摘录:

#include <boost/multi_array.hpp> 

#include <cassert> 

int main() 

{ 

    // Create a 3D array that is 3 x 4 x 2 

    typedef boost::multi_array< double, 3 > array_type; 

    typedef array_type::index index; 

    array_type A(boost::extents[3][4][2]); 


    // Assign values to the elements 

    int values = 0; 

    for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j) 

     for(index k = 0; k != 2; ++k) 

     A[i][j][k] = values++; 

    // Verify values 

    int verify = 0; 

    for(index i = 0; i != 3; ++i) 

    for(index j = 0; j != 4; ++j) 

     for(index k = 0; k != 2; ++k) 

     assert(A[i][j][k] == verify++); 

    return 0; 

} 
2

作为另一替代,STLSoft包括fixed_array_2d类(以及3D和4D的版本)。与这里给出的自制解决方案相比,它具有类似的实现,但是具有更完整的功能集(完全支持迭代器等)。与boost :: multi_array相比,它的重量更轻,更容易处理不符合标准的C++编译器,但(故意)缺少一些multi_array的特性。

0

在另一个线程后的再现。它完全符合你的要求,而不需要提前知道数组的大小,也不需要使用boost或STL。

赫雷什其中分配尺寸的3D阵列的例行N1 X N2 N3 X在连续的内存空间,同时允许你的一个[i] [j] [k]的对操作员访问语法。该阵列是动态但连续的,因此它比新[]调用的方法和循环更具优势。

template <class T> T ***Create3D(int N1, int N2, int N3) 
{ 
    T *** array = new T ** [N1]; 

    array[0] = new T * [N1*N2]; 

    array[0][0] = new T [N1*N2*N3]; 

    int i,j,k; 

    for(i = 0; i < N1; i++) { 

     if (i < N1 -1) { 

      array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]); 

      array[i+1] = &(array[0][(i+1)*N2]); 

     } 

     for(j = 0; j < N2; j++) {  
      if (j > 0) array[i][j] = array[i][j-1] + N3; 
     } 

    } 

    cout << endl; 
    return array; 
}; 

template <class T> void Delete3D(T ***array) { 
    delete[] array[0][0]; 
    delete[] array[0]; 
    delete[] array; 
}; 

在你随后的执行程序。...

int *** array3d; 
int N1=4, N2=3, N3=2; 

int elementNumber = 0; 

array3d = Create3D<int>(N1,N2,N3); 

//equivalently, a 'flat' array could be obtained with 
//int * array = array3d[0][0]; 

cout << "{" << endl; 
for (i=0; i<N1; i++) { 
    cout << "{"; 
    for (j=0; j<N2; j++) { 
     cout << "{"; 
     for (k=0; k<N3; k++) { 
      array3d[i][j][k] = elementNumber++; 
      cout << setw(4) << array3d[i][j][k] << " "; 

      //or if you're using the flat array: 
      //array[i*N2*N3 + j*N3 + k] = elementNumber++; 

     } 
     cout << "}"; 
    } 
    cout << "}"; 
    cout << endl ; 
} 
cout << "}" << endl; 

Delete3D(array3d); 

给人的输出:

{ 
{{ 0 1 }{ 2 3 }{ 4 5 }} 
{{ 6 7 }{ 8 9 }{ 10 11 }} 
{{ 12 13 }{ 14 15 }{ 16 17 }} 
{{ 18 19 }{ 20 21 }{ 22 23 }} 
}