2011-09-29 82 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塊永遠不會被觸發,並且矩陣必須在程序正常退出的途中被刪除。