In C++ FAQ, the [16.16] gives the following example,
void manip开发者_运维百科ulateArray(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;
}
Why we have to use delete this way, I mean,
First delete[] matrix[i-1];
then delete[] matrix;
Moreover, what’s the point of after the whole “try…catch” cycle, we still have to put
for (unsigned i = nrows; i > 0; --i)
delete[] matrix[i-1];
delete[] matrix;
at the end of this function.
What you're missing is the horribly evil indentation.
delete matrix[i-1];
happens once per loop iteration and deletes the nested arrays.
delete matrix
happens just one time after the loop completes and deletes the outer array.
Never write code like this in C++, use vector<vector<T> >
instead.
The reason the deletes also exist in the catch is because if you catch an exception you're still responsible to clean up the memory you allocated.
The
try/catch
block is necessary to ensure proper clean-up even if an exception is thrown anywhere in the code before the normal clean-up happens. This includes an exception in one of thenew
expressions. Thedelete[]
is safe because all the relevant pointers were initially set to zero, so that the deletion is valid even if no allocation ever occurred.(Note that if any exception does occur, it will still be propagated outside the function. The local
try/catch
block only ensures that the function itself doesn't leak any memory.)There are two sets of arrays: one is the outer array
matrix
, which is an array of pointers. This array gets allocated first and deleted last. Second, each elementmatrix[i]
is itself a pointer to an array ofFred
elements. Each array gets allocated in the firstfor
loop, and thus has to be deleted in another loop at the end.
When you in a loop deleting each of the rows, you're freeing up the memory allocated to the corresponding row. Then you need to free up the memory allocated for the pointers to each row.
Think of it this way:
FredPtr* matrix = new FredPtr[nrows];
allocates an array of pointers to rows - and it will need to be freed up at the end.
Then for each of the rows,
matrix[i] = new Fred[ ncols[i] ];
allocates memory for an array of pointers to columns - and it will need to be freed up separately.
yes, that is not a quality of an example-code but it is working fine. The copy-pasted code in the catch-block and after the catch-block is needed because in case of an exception the memory should be freed and in this case the exception is forwarded to the caller of that function. if you dont want to forward that exception you can delete the code inside the catch-block (but at least a console-output would be nice ;) )
The catch block in the try...catch is there to delete the matrix if an exception was thrown, and then re-throw the exception.
If no exception is thrown, the catch block never gets hit, and the matrix has to be deleted on the way out through the normal exit of the routine.
精彩评论