代码之家  ›  专栏  ›  技术社区  ›  eplawless

堆上的C++多维数组

  •  22
  • eplawless  · 技术社区  · 16 年前

    12 回复  |  直到 3 年前
        1
  •  24
  •   Johannes Schaub - litb    16 年前

    如果您已经知道嵌套维度的大小,还可以使用新的:

    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

        2
  •  6
  •   e.James    16 年前

    为了完整性,当你提前知道数组边界时,这里有一个更好的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
  •   Benoît photo_tom    16 年前

    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
  •  6
  •   seaotternerd    9 年前
        5
  •  4
  •   MSalters    16 年前

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

        6
  •  4
  •   Head Geek    16 年前

    boost::multi_array

        7
  •  3
  •   eplawless    16 年前

    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;
    
        8
  •  2
  •   e.James    16 年前

    循环不会将指针值写入 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;
        9
  •  2
  •   Josh Kelley    16 年前

    作为另一种选择, STLSoft fixed_array_2d 类(以及3D和4D版本)。与这里给出的自制解决方案相比,它有一个类似的实现,但有一个更完整的功能集(完全支持迭代器等)。与Boo::Mulk数组相比,它的重量更轻,更容易与C++编译器不兼容,但是(故意)缺少多数组的特性。

        10
  •  0
  •   Rich    16 年前

    不知何故,对于简单的2D数组,我更喜欢这种表示法,因为我不需要担心指针的嵌套级别。缺点是梅西耶指数符号。下面是一个包含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';
    }
    
        11
  •  0
  •   v.chaplin    11 年前

    这是另一个帖子的复制品。它完全满足您的需要,无需提前知道阵列尺寸,也无需使用boost或STL。

    下面是一个例程,它在连续内存空间中分配尺寸为N1 x N2 x N3的3D数组,同时允许您使用a[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 }}
    }