Ответ 1
В типичной реализации размер динамического блока памяти каким-то образом сохраняется в самом блоке - это правда. Но нет стандартного способа доступа к этой информации. (Реализации могут предоставить конкретные способы реализации для доступа к нему). Так оно и есть с malloc/free
, так оно и есть с new[]/delete[]
.
Фактически, в типичной реализации необработанные выделения памяти для вызовов new[]/delete[]
в конечном итоге обрабатываются некоторой специфичной для реализации парой malloc/free
, что означает, что delete[]
действительно не нужно заботиться о том, сколько памяти для освобождения: он просто вызывает это внутреннее free
(или то, что он назван), что позаботится об этом.
То, что delete[]
действительно нужно знать, - это то, сколько элементов нужно разрушать в ситуациях, когда тип элемента массива имеет нетривиальный деструктор. И в этом ваш вопрос - количество элементов массива, а не размер блока (эти два не совпадают, блок может быть больше, чем требуется для самого массива). По этой причине количество элементов в массиве обычно также сохраняется внутри блока с помощью new[]
и затем извлекается delete[]
для выполнения правильного уничтожения элемента массива. Нет стандартных способов доступа к этому номеру.
(Это означает, что в общем случае типичный блок памяти, выделенный new[]
, будет независимо, одновременно хранить как размер физического блока в байтах, так и количество элементов массива. Эти значения хранятся на разных уровнях механизма распределения памяти С++ - raw memory allocator и new[]
соответственно - и не взаимодействуют друг с другом каким-либо образом).
Однако обратите внимание, что по вышеуказанным причинам подсчет элемента массива обычно сохраняется только тогда, когда тип элемента массива имеет нетривиальный деструктор. То есть этот счет не всегда присутствует. Это одна из причин, по которой предоставление стандартного способа доступа к этим данным не представляется возможным: вам нужно либо хранить его всегда (что отнимает память), либо ограничивать его доступность по типу деструктора (что запутывает).
Чтобы проиллюстрировать это, при создании массива int
s
int *array = new int[100];
размер массива (т.е. 100
) обычно не сохраняется new[]
, так как delete[]
не заботится об этом (int
не имеет деструктора). Физический размер блока в байтах (например, 400 байт или более) обычно сохраняется в блоке с помощью распределителя необработанной памяти (и используется средством освобождения памяти, вызванным delete[]
), но он может легко оказаться 420 по какой-то конкретной причине. Таким образом, этот размер в основном бесполезен для вас, так как вы не сможете получить из него точный размер оригинального массива.