如何完全删除二维指针数组

3
我有一个C++中的二维指针矩阵,例如:
typedef unsigned char  U8;
typedef unsigned int   U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
    A[i] = new U8[m_L];
}

在设置A0的值后,我将编写一个函数,根据随机数是0还是1来决定是否删除A中的M-2行。
void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
     }
  }
}

现在,在包含A内存分配的主函数中,我想释放/删除为A分配的内存。我可以使用以下代码:
//free A matrix
for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}
delete[] A;
A = NULL;

我的问题是,我不知道A是否删除了M-2行。因此,如果我的随机数是0,上面的代码显然会删除所有内存。这意味着,只有在delete_or_not函数中删除M-2行时,上面的代码才会正确地删除内存。如何完美地删除A矩阵。谢谢。
最终,我的完整代码是:
typedef unsigned char  U8;
typedef unsigned int   U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
    A[i] = new U8[m_L];
}
delete_or_not(A,M);
//free A matrix 
//Way 1: will miss M-2 row if delete_or_not function did not delete 2 rows.
// It only correct if rand_num=1
for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}
delete[] A;
A = NULL;

//Way 2- It will correct if the size of A is M by M

for (U32 i = 0; i < M; ++i)
{
      delete[] A[i];
      A[i] = NULL;
}
delete[] A;
A = NULL;

1
有比 U32U8Mm_L 等更易读的名称可供选择。 - Paul Evans
1
不要使用原始数组、指针、newnew[],这样就不必担心它们了。 - n. m.
1
还要注意的是,您的描述和代码并不相同。您的描述中写着:“删除或不删除M-2行”,但实际上您的代码删除了2个元素,因为在for循环中,您将U32 index = M-2作为索引的初始化。 - Support Ukraine
2个回答

4

只需将已删除的元素设置为NULL,一切都会正常工作:

void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
        A[index] = NULL;
     }
  }
}

此外,这并不是非常有用:
for (U32 i = 0; i < M; ++i)
{
    if (i < m_L)
    {
      delete[] A[i];
      A[i] = NULL;
    }
}

如果i小于m_L,那么将i从0增加到M是没有意义的。


但实际上,在C++中,您应该使用std::vector<std::vector<U8>>,并简单地使用erasepop_back来删除“行”。


抱歉,也许我之前的解释有误。我的期望是,在调用delete_or_not函数后如何删除矩阵A。我会更新。 - Jame
@user8430 - 你试过我的建议解决方案了吗? - Amit

1
void delete_or_not中,你应该像Amit的另一个答案所建议的那样将删除的元素设置为NULL。
然后,你发布的代码的Way 2在两种情况下都是正确的。
在NULL上调用delete是完全合法的,不会有任何影响。
Way 1不起作用,应该被删除。
总之:
void delete_or_not(U8** A,int M) 
{
  if (rand_num==1){
     for (U32 index = M-2; index < M; ++index){
        delete[] A[index];
        A[index] = NULL;    // Add this to your code
     }
  }
} 


// In main somewhere...

// free A
for (U32 i = 0; i < M; ++i)
{
      delete[] A[i];   // Not a problem if the element has already been deleted
                       // because the pointer will be NULL and calling
                       // delete with NULL is OK (and changes nothing)
      A[i] = NULL;
}
delete[] A;
A = NULL;

谢谢。但是如果random_num=1,第二种方法会崩溃。因此,在delete_or_not函数中已经删除了2行。因此,对于=1到M不正确。 - Jame
不会崩溃,如果你按照Amit提出的更改进行操作。 - Support Ukraine
我又添加了一次。谢谢。现在它可以工作了。感谢您的解释。 - Jame

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