关于堆的C ++多维数组

时间:2008-12-04 15:18:41

标签: c++ arrays memory heap allocation

我将如何动态分配多维数组?

11 个答案:

答案 0 :(得分:24)

如果您已经知道嵌套尺寸的大小,您还可以使用new来分配多维数组:

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使得更容易阅读代码。

答案 1 :(得分:6)

看到这个: C++ FAQ by Marshall Cline

请参阅“如何使用new分配多维数组?”和“但以前的常见问题解答的代码是SOOOO棘手和容易出错!是不是有一个更简单的方法?”部分。

答案 2 :(得分: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);

答案 3 :(得分: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;

}

答案 4 :(得分:3)

这是我得到的实施;我声明了int s的单个连续块,而不是在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;

答案 5 :(得分:3)

应该提到

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

答案 6 :(得分:3)

我很惊讶没人提到boost::multi_array。上周我在一个程序中需要一个2D数组,发现它比我之前提出的自制解决方案更容易,编码更快(所有这些都在其他评论中提到)

答案 7 :(得分: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;

答案 8 :(得分:2)

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

答案 9 :(得分:0)

如果只是在正确数量的元素上空间,则可以将一维索引为2,3维或N维。例如,如果我有10行10列,我知道如果我在第3行,我将不得不超过至少30个元素来实现它。

不知何故,我更喜欢这种符号用于简单的2D数组,因为我不需要担心嵌套的指针级别。缺点是杂乱的指数表示法。这是一个包含n行和m列的2D数组的示例:

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';
}

答案 10 :(得分:0)

这是另一个帖子上的帖子的再现。它完全符合您的要求,无需提前知道数组维度,也无需使用boost或STL。

这是一个例程,它在连续的内存空间中分配维度为N1 x N2 x N3的3D数组,同时允许运算符访问的a [i] [j] [k]语法。数组是动态的但是连续的,所以它比矢量&lt;&gt;大得多。新[]调用的方法和循环。

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 }}
}