Всякий раз, когда кто-то говорит int* nums = new int[3]
, система времени выполнения обязана хранить количество объектов, 3
, в месте, которое можно получить, зная только указатель, nums
. Компилятор может использовать любую технику, которую захочет, но есть две популярные.
Код, сгенерированный nums = new int[3]
, может хранить число 3
в статическом ассоциативном массиве, где указатель nums
используется в качестве ключа поиска, а число 3
является ассоциированным значением. Код, сгенерированный delete[] nums
, ищет указатель в ассоциативном массиве, извлекает связанный size_t, а затем удаляет запись из ассоциативного массива.
Код, сгенерированный nums = new int[3]
, может выделить дополнительный размер памяти (size_t) байтов (возможно, плюс несколько байтов выравнивания) и поместить значение 3
непосредственно перед первым int
объектом. Тогда delete[] nums
найдет 3
, посмотрев на фиксированное смещение перед первым int
объектом (то есть до *num
), и освободит память, начиная с начала выделения (то есть блока память начинает фиксированное смещение до *nums
).
Ни одна техника не идеальна. Вот несколько компромиссов.
Метод ассоциативного массива медленнее, но безопаснее: если кто-то забудет []
при освобождении массива вещей, (a) запись в ассоциативном массиве будет утечкой, и (b) только первый объект в массив будет разрушен. Это может быть или не быть серьезной проблемой, но, по крайней мере, это может не привести к сбою приложения.
Техника перераспределения быстрее, но более опасна: если кто-то скажет delete nums
, где он должен был сказать delete[] nums
, адрес, который передается оператору delete(void* nums)
, не будет правильным распределением кучи - это будет по крайней мере sizeof(size_t)
байт после правильного выделения кучи. Это, вероятно, повредит кучу. - C ++ FAQs