简体   繁体   English

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

[英]How can I properly fill a 2D array that is allocated on the heap?

I have created a two dimensional array on the heap. 我在堆上创建了一个二维数组。 And I want to fill the array with numbers. 我想用数字填充数组。 I have tried two ways of doing this. 我尝试了两种方法。 The first attempt sort of works, but the problem is that the program will crash when I try to delete it. 第一次尝试是可行的,但是问题是,当我尝试删除程序时,该程序将崩溃。 The second attempt that I did made it possible to delete the array after I have used it, but the array is not filled the correct way. 使用后的第二次尝试使删除数组成为可能,但是数组未正确填充。

So here is how I declared the two dimensional array: 所以这是我声明二维数组的方式:

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

And then I fill it like this: 然后我像这样填充它:

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;

When I am filling it this way the array is behaving the way I want and I am getting the expected result in a later method that uses this array. 当我以这种方式填充数组时,它的运行方式就是我想要的方式,而在使用此数组的后续方法中,我得到了预期的结果。

However when I try to delete it: 但是,当我尝试删除它时:

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

I get an thrown exception with the following error message "Test.exe has triggered a breakpoint." 我收到以下错误消息“ Test.exe触发了断点”,引发了异常。 And of course if I run it in release the program will crash. 当然,如果我在发行版中运行该程序,它将崩溃。

My second attempt of filling the array looked like this: 我第二次尝试填充数组如下所示:

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;

And now there is no problem when I am deleting the array, but now the array is not behaving the way I want it to, and when I test the method that uses the array I get the same result as if the array would just have been filled with zeros. 现在,当我删除数组时没有问题,但是现在数组没有表现出我想要的方式,并且当我测试使用数组的方法时,我得到的结果与数组刚好一样充满零。

I know that I am not doing it right in the second attempt but I just did this to see what had to be done so the array could be succesfully deleted. 我知道我在第二次尝试中做的并不正确,但是我只是这样做以查看必须执行的操作才能成功删除阵列。

So to sum this up my question is how should I fill the two dimensional array in a way that it is correctly filled, but it will also succesfully be deleted? 因此,总而言之,我的问题是如何以正确填充的方式填充二维数组,但也会成功将其删除?

Thanks! 谢谢!

Fast answer : don't use raw arrays, it's C++, just use std::vector<int>/std::array<int> which properly overloads operator= and they will do the work for you, eg: 快速答案 :不要使用原始数组,它是C ++,只需使用std::vector<int>/std::array<int>正确重载operator= ,它们将为您完成工作,例如:

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

Long answer : 长答案

You are not filling the arrays on the heap, rather you are replacing their reference in matrix with local arrays which get deleted when exiting the scope and can't be deleted at all in any case. 您不是要在堆上填充数组,而是要用本地数组替换它们在matrix的引用,这些数组在退出作用域时会被删除,并且在任何情况下都无法删除。

To explain the issue let's keep it simple, suppose a single array on the heap 为了解释这个问题,让我们保持简单,假设堆上有一个数组

int* row = new int[rowSize];

So you have a variable row which stores a memory address to the array allocated on heap: 因此,您具有一个可变行,该行将内存地址存储到在堆上分配的数组中:

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

Now you do: 你现在做:

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

and what happens is that myRow is allocated on stack and its address is stored inside row variable which ends up with a situation like: 并且发生的是myRow被分配在堆栈上,并且其地址存储在row变量内,最终导致如下情况:

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

So you've lost any reference to the array on heap and row points to an address on stack. 因此,您丢失了对堆上数组的任何引用,并且row指向了栈上的地址。 You can't delete row anymore and data pointed by it will become garbage when exiting the scope. 您无法再删除row ,并且退出范围时,它所指向的数据将变成垃圾。 You didn't copy anything in the end. 最后,您没有复制任何内容。

To properly copy data you could use std::copy , eg: 要正确复制数据,您可以使用std::copy ,例如:

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

< Mandatory "You should just use a 2D std::vector instead!!" <强制性的“您应该只使用2d std :: vector来代替!” rant (no but really, all of this would be easier if you just used a vector) > rant(不,但实际上,如果您只是使用矢量,所有这些操作都将更加容易)>

Let's look at what you're doing for one of the elements: 让我们看看您正在为以下元素之一做什么:

matrix[2] = new int[ColSize];

matrix[2] (which is an int* ) is given the address of a new array you've allocated on the heap. matrix[2] (它是一个int* )提供了您在堆上分配的新数组的地址。

matrix[2] = matrixI2;

Throw out the old value of matrix[2] (the pointer to the array on the heap), causing the old dynamically allocated array to be lost, and point matrix[2] to the local array, matrixI2 . 丢弃matrix[2]的旧值(指向堆上数组的指针),使旧的动态分配数组丢失,并将matrix[2]指向本地数组matrixI2

If matrixI2 goes out of scope, our pointer is now invalid. 如果matrixI2超出范围,则我们的指针现在无效。 Also, there's no need to delete matrix[2] , since it's not pointing to dynamically allocated memory. 同样,也不需要delete matrix[2] ,因为它没有指向动态分配的内存。

Instead what you want is probably: 相反,您想要的可能是:

matrix[2] = new int[12]{1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1};

for each index instead of your loop. 为每个索引而不是循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM