如何正确填充在堆上分配的2D数组?

时间:2018-10-25 16:04:33

标签: c++ arrays

我在堆上创建了一个二维数组。我想用数字填充数组。我尝试了两种方法。第一次尝试是可行的,但是问题是,当我尝试删除程序时,该程序将崩溃。使用后的第二次尝试使删除数组成为可能,但数组未正确填充。

这就是我声明二维数组的方式:

int** matrix = new int*[rowSize];
for (int i = 0; i < rowSize; i++) {
    matrix[i] = new int[ColSize];
}

然后我像这样填充它:

int matrixI0[]{1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1};
int matrixI1[]{1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1};
int matrixI2[]{1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1};
int matrixI3[]{1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI4[]{1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI5[]{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI6[]{0, 0, 1, 0, 0, 0, 1, 1, 1, 0 ,0, 1};


matrix[0] = matrixI0;
matrix[1] = matrixI1;
matrix[2] = matrixI2;
matrix[3] = matrixI3;
matrix[4] = matrixI4;
matrix[5] = matrixI5;
matrix[6] = matrixI6;

当我用这种方式填充数组时,它的运行方式就是我想要的,而在使用此数组的以后的方法中,我得到了预期的结果。

但是,当我尝试删除它时:

    for (int i = 0; i < rowSize; ++i) {
    delete[] matrix[i];
}
delete[] matrix;

我收到带有以下错误消息“ Test.exe触发了断点”的异常。当然,如果我在发行版中运行该程序,它将崩溃。

我第二次尝试填充数组的尝试如下:

int matrixI0[]{1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1};
int matrixI1[]{1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1};
int matrixI2[]{1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1};
int matrixI3[]{1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI4[]{1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI5[]{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1};
int matrixI6[]{0, 0, 1, 0, 0, 0, 1, 1, 1, 0 ,0, 1};


matrix[0][0] = *matrixI0;
matrix[1][0] = *matrixI1;
matrix[2][0] = *matrixI2;
matrix[3][0] = *matrixI3;
matrix[4][0] = *matrixI4;
matrix[5][0] = *matrixI5;
matrix[6][0] = *matrixI6;

现在,当我删除数组时没有问题,但是现在数组没有表现出我想要的方式,当我测试使用数组的方法时,我得到的结果与数组会得到的结果相同只是已经充满了零。

我知道我在第二次尝试中操作不正确,但是我只是这样做是为了查看必须执行的操作才能成功删除数组。

因此,总而言之,我的问题是我应该如何以正确填充二维数组的方式填充二维数组,但它也会成功删除?

谢谢!

2 个答案:

答案 0 :(得分:2)

快速答案:不要使用原始数组,它是C ++,只需使用std::vector<int>/std::array<int>即可适当地重载operator=,它们将为您完成工作,例如:< / p>

std::vector<std::vector<int>> matrix(7);
matrix[0] = { 1, 3, 3};

好答案

您不是要填充堆上的数组,而是要用本地数组替换matrix中对它们的引用,这些本地数组在退出范围时会被删除,并且在任何情况下都无法删除。

为解释这个问题,让我们保持简单,假设堆上有一个数组

int* row = new int[rowSize];

因此,您有一个可变行,用于存储分配给堆上分配的数组的内存地址:

| row | ------> |x|x|x|x|x|x|x|

现在您要做:

int myRow[] = { 1, 2, 3};
row = myRow;

发生的情况是myRow被分配在堆栈上,其地址存储在row变量内,最终导致如下情况:

| row |         |x|x|x|x|x|x|x|
   |
   --> |y|y|y|y|y|y|y|

因此,您丢失了对堆上数组的任何引用,row指向堆栈上的地址。您无法再删除row,并且它指向的数据在退出范围时将变为垃圾。最后没有复制任何内容。

要正确复制数据,可以使用std::copy,例如:

int myRow[] = { 1, 2, 3};
std::copy(myRow, myRow + rowSize, row);

答案 1 :(得分:2)

<强制性的“您应该使用2D std :: vector代替!”咆哮(不,但实际上,如果您只是使用向量,所有这些操作都会更容易)>

让我们看看您正在为以下元素之一做什么:

matrix[2] = new int[ColSize];

matrix[2](即int*)提供了您在堆上分配的新数组的地址。

matrix[2] = matrixI2;

丢弃旧值matrix[2](指向堆上数组的指针),导致旧的动态分配数组丢失,并将matrix[2]指向本地数组{{1 }}。

如果matrixI2超出范围,则我们的指针现在无效。此外,由于它没有指向动态分配的内存,因此无需matrixI2

相反,您想要的可能是:

delete matrix[2]

每个索引而不是循环。