【问题标题】:Declaring a pointer to multidimensional array and allocating the array声明指向多维数组的指针并分配数组
【发布时间】:2011-04-23 16:25:50
【问题描述】:

我已经尝试过寻找,但我没有找到任何有明确答案的东西。我知道我的问题不会那么难。也许只是我累了..

基本上,我想声明一个指向二维数组的指针。我想这样做,因为最终我将不得不调整数组的大小。我用一维数组成功完成了以下操作:

int* array;
array = new int[somelength];

我想对二维数组执行以下操作,但无法编译:

int* array;
array = new int[someheight][somewidth];

编译器给我一个错误,指出“somewidth”不能出现在常量表达式中。我尝试了 ** 和 [][] 的各种组合,但它们似乎都不起作用。我知道这并不复杂...感谢任何帮助。

【问题讨论】:

    标签: c++ pointers multidimensional-array


    【解决方案1】:
    const int someheight = 3;
    const int somewidth = 5;
    
    int (*array)[somewidth] = new int[someheight][somewidth];
    

    【讨论】:

    • 与这里的其他答案不同,这个答案实际上回答了这个问题,即如何声明指向多维数组的指针 - 而不是锯齿状数组。这是对性能敏感的应用程序的重要区别。如果“somewidth”是一个常数,它会起作用,并且只有“someheight”会发生变化。如果你看看这个 2D 数组是如何在内存中布置的——它是一起的并且是连续的,只完成了一个“新”内存分配。如果宽度也是动态的,Alexander Rafferty 的回答也很好。其他答案很慢,因为他们做了很多 malloc...
    • 如何正确销毁这个数组?删除[] 数组;我认为是这样,因为它确实是一段连续的记忆。
    • 只是为了澄清詹姆斯约翰斯顿的重要说明。数组和指针不一样:数组可以衰减为指针,但指针不携带有关其指向的数据的大小/配置的状态。这可以防止将指针的指针用作连续内存。 C++ 仍然允许将 N 维数组衰减为指向 N-1 维数组的指针,因为您可能会丢失最左边的维度并且仍然能够正确访问具有 N-1 维信息的数组元素。详情在stackoverflow.com/a/3925968/1201614
    【解决方案2】:

    我刚刚发现这个古老的答案仍然被阅读,这很遗憾,因为它是错误的。看看the answer below 的全部票数。


    阅读指针语法,您需要一个数组数组。这与指向指针的指针相同。

    int width = 5;
    int height = 5;
    int** arr = new int*[width];
    for(int i = 0; i < width; ++i)
       arr[i] = new int[height];
    

    【讨论】:

    • 你试过了吗?它不编译(如果高度和宽度都是变量)
    • 是的,我已经尝试过了,但编译器仍然出现同样的错误。它会说“‘width’不能出现在常量表达式中”
    • 如果我要访问这个数组的一个元素,它只是 arr[width][height]?
    • 太棒了。感谢您的帮助。
    • 不,数组数组和指针数组不是一回事。为什么这个帖子被接受? Tony The Lion 的答案是正确的,这个是完全错误的。
    【解决方案3】:

    一个来自here 的现成示例,在谷歌搜索几秒钟后使用短语“二维动态数组”:

    int **dynamicArray = 0;
    
    // memory allocated for elements of rows. 
    dynamicArray = new int *[ROWS];
    
    // memory allocated for  elements of each column.  
    for( int i = 0 ; i < ROWS ; i++ ) {
        dynamicArray[i] = new int[COLUMNS];
    }
    
    // free the allocated memory 
    for( int i = 0 ; i < ROWS ; i++ ) {
        delete [] dynamicArray[i];
    }
    delete [] dynamicArray;
    

    【讨论】:

    • 这是一个数组数组,并不是真正的二维数组。
    • @Alexander Rafferty:我明白了——“数组数组”和“二维数组”有什么区别?
    • @ArunSaha,这是旧的,但要回答您的问题以及其他任何偶然发现此问题的人,二维数组在内存中是连续的;动态数组的动态数组在第一维是连续的,但是在第二维的每个数组是分开存储的
    • @Stephen Lin:感谢您的解释!假设还有一个int staticArray[ ROWS ][ COLUMNS ];。还假设有一个函数printArray( int arr[ ROWS ][ COLUMNS ] ) 访问并打印所有元素为arr[ i ][ j ]。可以将staticArraydynamicArray 传递给该函数,它会起作用,对吗?存在结构差异,您的观点是有效的。但是,由于没有行为差异,我倾向于将差异视为实现细节。
    • @ArunSaha,不是重点,您可以将int[N]N 整数数组)作为int *(指向整数的指针)传递,但您不能传递int[R][C](数组C 整数数组的 R)作为int **(指向整数的指针);没有隐式转换,如果您将其转换为使其工作,您将破坏内存; int [R][C] 衰减为 int (*)[C](指向 C 整数数组的指针)...请参阅 this answer
    【解决方案4】:

    我建议使用比数组数组更简单的方法:

    #define WIDTH 3
    #define HEIGHT 4
    
    int* array = new int[WIDTH*HEIGHT];
    int x=1, y=2, cell;
    cell = array[x+WIDTH*y];
    

    我认为这比数组中的数组更好,因为分配要少得多。你甚至可以编写一个辅助宏:

    #define INDEX(x,y) ((x)+(WIDTH*(y)))
    
    int cell = array[INDEX(2,3)];
    

    【讨论】:

      【解决方案5】:

      就个人而言,我的偏好是使用语法技巧来声明指向动态大小的多维数组的指针。这适用于支持可变长度数组 (VLA) 的编译器(所有 C++ 编译器都应该),以及大多数当前的 C 编译器。

      基本思想体现在:

      void bar (int *p, int nz, int ny, int nx) {
        int (*A)[ny][nx] = (int(*)[ny][nx]) p;
      

      "p" 指向您希望将其视为多维数组的(连续)空间块。 “A”与“p”具有相同的值,但该声明使编译器以您想要的多维方式处理对“A”的引用。 例如:

      #include <iostream>
      using namespace std;
      
      void bar (int *p, int nz, int ny, int nx)
      {
        int (*A)[ny][nx] = (int(*)[ny][nx]) p;
      
        for (int ii = 0; ii < nz; ii++) {
          for (int jj = 0; jj < ny; jj++) {
            for(int kk = 0; kk < nx; kk++) {
                A[ii][jj][kk] = ii*1000000 + jj*1000 + kk;
            }
          }
        }
      }
      
      
      void out (int *p, int nz, int ny, int nx)
      {
        int (*A)[ny][nx] = (int(*)[ny][nx]) p;
        cout << A[11][22][33] << endl;
      }
      
      
      int main (void)
      {
        int NX = 97;
        int NY = 92;
        int NZ = 20;
        int *space = new int [NZ * NY * NX];
      
        bar (space, NZ, NY, NX);
        out (space, NZ, NY, NX);
        return 0;
      }
      

      运行它会产生输出“11022033”

      “A”别名的声明看起来有点奇怪,但它允许您直接简单地使用所需的多维数组语法

      【讨论】:

        【解决方案6】:

        我觉得这样就可以了

        int r, c ;
        std::cin>>r>>c ;
        int *array = new int[r*c] ; 
        

        你可以通过这样的方式输入值

        for (int i = 0 ; i < r ; i++){
            for (int j = 0 ; j < c ; j++){
                std::cin>>array[i *c + j] ; 
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多