2011-09-29 105 views
1

在C++中常见问题,在[16.16]给出了下面的例子,删除多维数组

void manipulateArray(unsigned nrows, unsigned ncols[]) 
{ 
    typedef Fred* FredPtr; 
    FredPtr* matrix = new FredPtr[nrows]; 

    // Set each element to NULL in case there is an exception later. 
    // (See comments at the top of the try block for rationale.) 
    for (unsigned i = 0; i < nrows; ++i) 
     matrix[i] = NULL; 
    try { 
    for (unsigned i = 0; i < nrows; ++i) 
    matrix[i] = new Fred[ ncols[i] ]; 
    for (unsigned i = 0; i < nrows; ++i) { 
     for (unsigned j = 0; j < ncols[i]; ++j) { 
     someFunction(matrix[i][j]); 
     } 
     } 

    if (today == "Tuesday" && moon.isFull()) { 
     for (unsigned i = nrows; i > 0; --i) 
     delete[] matrix[i-1]; 
     delete[] matrix; 
     return; 
    } 

...code that fiddles with the matrix... 

    } 
    catch (...) { 
    for (unsigned i = nrows; i > 0; --i) 
     delete[] matrix[i-1]; 
     delete[] matrix; 
     throw; // Re-throw the current exception 
    } 

    for (unsigned i = nrows; i > 0; --i) 
    delete[] matrix[i-1]; 
    delete[] matrix; 
    } 

为什么我们要使用删除这种方式,我的意思是,

首先delete[] matrix[i-1]; 然后delete[] matrix;

此外,整个“try ... catch”循环之后有什么意义呢,我们还是要把

for (unsigned i = nrows; i > 0; --i) 
    delete[] matrix[i-1]; 
    delete[] matrix; 

在此功能的结尾。

+1

这段代码实际上是关于一个很好的例子,什么例外的是,他们都没有,和如何使用它们的内容:异常信号异常情况,它们是*不*错误代码。 –

回答

2
  1. try/catch块是必要的,以确保适当的清理,即使有异常任何地方的代码正常清理发生之前抛出。这包括new表达式中的一个例外。 delete[]是安全的,因为所有相关的指针最初都设置为零,所以即使没有发生分配,删除也是有效的。

    (请注意,如果发生任何异常,但仍然会在函数外传播,当地try/catch块仅保证函数本身不会泄露任何内存。)

  2. 有两套数组:一个是外部数组matrix,它是一个指针数组。这个数组首先被分配,最后被删除。其次,每个元素matrix[i]本身是指向数组Fred元素的指针。每个数组在第一个for循环中被分配,因此必须在最后的另一个循环中被删除。

9

你失踪的是可怕的邪恶缩进。

delete matrix[i-1];每循环迭代一次并删除嵌套数组。 delete matrix仅在循环完成后发生一次,并删除外部数组。

千万不要在C++中编写这样的代码,而应该使用vector<vector<T> >

删除在catch中也存在的原因是因为如果你发现异常,你仍然有责任清理你分配的内存。

1

当你在循环中删除每一行时,你将释放分配给相应行的内存。然后你需要释放分配给每行指针的内存。

认为它是这样的:

FredPtr* matrix = new FredPtr[nrows]; 

分配指针数组行 - 这将需要在年底前被释放。

然后,对于每一行,

matrix[i] = new Fred[ ncols[i] ]; 

分配内存指针数组的列 - 和它会需要单独释放。

0

是的,这不是一个示例代码的质量,但它工作正常。在catch-block之后和catch-block之后的复制粘贴代码是需要的,因为如果发生异常,内存应该被释放,并且在这种情况下,异常被转发给该函数的调用者。如果你不想转发该异常,你可以删除catch-block内部的代码(但至少有一个控制台输出会很好;))

0

try ... catch中的catch块在那里删除矩阵如果抛出异常,然后重新抛出异常。

如果没有抛出异常,catch块永远不会被触发,并且矩阵必须在程序正常退出的途中被删除。