正确初始化多维动态指针数组的方法是什么?

27

我在将动态指针排列为2维及以上时一直遇到问题,例如我想要一个指向2D数组的指针。我知道:

int A[3][4];
int (*P)[4] = A;

完全合法(即使我不完全理解为什么)。考虑到以下因素:

int *P = new int[4];

工作时,我想象过:

int **P = new int[5][7];

也可以工作,但事实并非如此。这段代码显示了错误:

Error: A value of type "(*)[7]" cannot be used to initialize an entity of
       type "int **"

看到这个,新的部分就成为我创建的一个包含7个整数数组的指针:

int (*P)[4] = new int[7][4];

这确实可以工作,但不是我想要实现的。这样做,我至少需要使用常量值来限制任何后续维度,但我希望它在运行时完全定义,因此是“动态”的。

我该如何让这个多维指针工作呢?


1
不要忘记删除它们。 - doctorlove
std::vector<std::unique_ptr<int>> - Chad
4个回答

75

让我们从一些基本示例开始。

当你说int *P = new int[4];时:

  1. new int[4];调用operator new函数()
  2. 为4个整数分配内存。
  3. 返回对该内存的引用。
  4. 要绑定此引用,您需要具有与返回引用相同类型的指针,因此您这样做

int *P = new int[4]; // As you created an array of integer
                     // you should assign it to a pointer-to-integer
对于多维数组,您需要分配一个指针数组,然后将该数组填充为指向数组的指针,如下所示:

对于多维数组,需要先创建一个指针数组,然后将其中每个元素指向一个数组,如下所示:

int **p;
p = new int*[5]; // dynamic `array (size 5) of pointers to int`

for (int i = 0; i < 5; ++i) {
  p[i] = new int[10];
  // each i-th pointer is now pointing to dynamic array (size 10)
  // of actual int values
}

以下是它的外观:

enter image description here

释放内存

  1. 对于一维数组,

     // need to use the delete[] operator because we used the new[] operator
    delete[] p; //free memory pointed by p;`
    
  2. 对于二维数组,

    // need to use the delete[] operator because we used the new[] operator
    for(int i = 0; i < 5; ++i){
        delete[] p[i];//deletes an inner array of integer;
    }
    
    delete[] p; //delete pointer holding array of pointers;
    

避免内存泄漏和悬空指针


7
你想要的是这样的东西:
int **P = new int*[7];
p[0] = new int[5];
p[1] = new int[5];
...

3
另一种方法是将一维数组用作二维数组。这样,您只需要分配一次内存(一个连续的块)即可;
int *array;
size_t row=5,col=5;
array = (int*)malloc(row*col*sizeof(int)) //or new int[row*col]

这将得到与"int array [5] [5]"相同的结果。 要访问字段,只需执行以下操作:
array[1 //the row you want
 * col //the number of columns
+2//the column you want
] = 4;

这相当于:

array[1][2];

3

这会在一些调试编译器上执行边界检查,使用动态大小并自动删除自己。唯一需要注意的是x和y的顺序相反。

std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size));

for (int y = 0; y < y_size; y++)
{
    for (int x = 0; x < x_size; y++)
    {
        array2d[y][x] = 0;
    }
}

2
不,它不执行边界检查。 - Ben Voigt
初始化也可以用以下方式完成。 std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size, 0)); - Kalyan Saha
还有第二个for循环的问题。应该使用x++而不是y++。 - Kalyan Saha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接