Why is there a special new and delete for arrays?
Objects created with new[]
must use delete[]
. Using delete
is undefined on arrays.
With malloc and free you have a more simple situation. There is only 1 function that frees the data you allocate, there is no concept of a destructor being called either. The confusion just comes in because delete[]
and delete look similar. Actually they are 2 completely different functions.
Using delete won't call the correct function to delete the memory. It should call delete[](void*)
but instead it calls delete(void*)
. For this reason you can't rely on using delete
for memory allocated with new[]
[16.13] Can I drop the
[]
when deleteing array of some built-in type (char, int, etc)?No!
Sometimes programmers think that the
[]
in thedelete[] p
only exists so the compiler will call the appropriate destructors for all elements in the array. Because of this reasoning, they assume that an array of some built-in type such aschar
orint
can bedelete
d without the[]
. E.g., they assume the following is valid code:void userCode(int n) { char* p = new char[n]; ... delete p; // ← ERROR! Should be delete[] p !}
But the above code is wrong, and it can cause a disaster at runtime. In particular, the code that's called for
delete p
isoperator delete(void*)
, but the code that's called fordelete[] p
isoperator delete[](void*)
. The default behavior for the latter is to call the former, but users are allowed to replace the latter with a different behavior (in which case they would normally also replace the corresponding new code in operatornew[](size_t)
). If they replaced thedelete[]
code so it wasn't compatible with the delete code, and you called the wrong one (i.e., if you saiddelete p
rather thandelete[] p
), you could end up with a disaster at runtime.
Why does delete[]
exist in the first place?
Whether you do x or y:
char * x = new char[100]; char * y = new char;
Both are stored in char *
typed variables.
I think the reason for the decision of delete
, and delete[]
goes along with a long list of decisions that are in favor of efficiency in C++. It is so that there is no enforced price to do a lookup of how much needs to be deleted for a normal delete operation.
Having 2 new
and new[]
seems only logical to have delete
and delete[]
anyway for symmetry.
The difference is that delete
will only delete the entire memory range, but will only call the destructor for 1 object. delete[]
will both delete the memory and call the destructor for every single object. If you do not use delete[]
for arrays, it's only a matter of time before you introduce a resource leak into your application.
EDIT Update
According to the standard, passing an object allocated with new[]
to delete
is undefined. The likely behavior is that it will act as I described.
Stroustrup talks about the reasons for separate new
/new[]
and delete/
delete[]` operators in "The Design and Evolution of C++" in sections 10.3 through 10.5.1:
- 10.3 Array Allocation - discusses that they wanted a way to allow arrays of objects to be allocated using a separate scheme from allocation single objects (ie., allocating arrays from a separate store). Adding the array versions of
new
anddelete
was a solution for this; - 10.5.1 Deallocating Arrays - discusses how a problem with deallocating arrays using just a single
delete
operator is that there needs to be more information than just the pointer in order to determine if the pointer points to the first element of an array or if it just points to a single object. Instead of "complicating the common case of allocating and deallocating individual objects", thedelete[]
operator is used to handle arrays. This fits in with the general C++ design philiosophy of "don't pay for what you don't use".
Whether this decision was a mistake or not is debatable - either way has good arguments, but we have what we have.