Whenever someone says int* nums = new int[3]
, the runtime system is required to store the number of objects, 3
, in a place that can be retrieved knowing only the pointer, nums
. The compiler can use any technique it wants to use, but there are two popular ones.
The code generated by nums = new int[3]
might store the number 3
in a static associative array, where the pointer nums
is used as the lookup key and the number 3
is the associated value. The code generated by delete[] nums
would look up the pointer in the associative array, would extract the associated size_t, then would remove the entry from the associative array.
The code generated by nums = new int[3]
might allocate an extra sizeof(size_t) bytes of memory (possibly plus some alignment bytes) and put the value 3
just before the first int
object. Then delete[] nums
would find 3
by looking at the fixed offset before the first int
object (that is, before *num
) and would deallocate the memory starting at the beginning of the allocation (that is, the block of memory beginning the fixed offset before *nums
).
Neither technique is perfect. Here are a few of the tradeoffs.
The associative array technique is slower but safer: if someone forgets the []
when deallocating an array of things, (a) the entry in the associative array would be a leak, and (b) only the first object in the array would be destructed. This may or may not be a serious problem, but at least it might not crash the application.
The overallocation technique is faster but more dangerous: if someone says delete nums
where they should have said delete[] nums
, the address that is passed to operator delete(void* nums)
would not be a valid heap allocation—it would be at least sizeof(size_t)
bytes after a valid heap allocation. This would probably corrupt the heap. - C++ FAQs