Почему не возможно получить доступ к размеру нового [] 'd массив?

Когда Вы выделяете использование массива new [], почему Вы не можете узнать размер того массива от указателя? Это должно быть известно во время выполнения, иначе delete [] не знал бы сколько памяти к свободному.

Если я не пропускаю что-то?

19
задан Sam 12 August 2014 в 09:28
поделиться

4 ответа

В типичной реализации размер блока динамической памяти каким-то образом хранится в самом блоке - это правда. Но стандартного способа доступа к этой информации не существует. (Реализации могут предоставлять специфические для конкретной реализации способы доступа к ней). Так обстоит дело с malloc/free, так обстоит дело с new[]/delete[].

Фактически, в типичной реализации необработанные выделения памяти для вызовов new[]/delete[] в конечном итоге обрабатываются некоторой специфичной для реализации парой malloc/free-подобной парой, что означает, что delete[] не нужно заботиться о том, сколько памяти деаллоцировать: он просто вызывает внутренний free (или как он там называется), который об этом позаботится.

Что delete[] действительно нужно знать, так это сколько элементов destruct в ситуациях, когда тип элемента массива имеет нетривиальный деструктор. И именно об этом - количестве элементов массива, а не о размере блока (это не одно и то же, блок может быть больше, чем действительно требуется для самого массива). По этой причине количество элементов в массиве обычно также хранится внутри блока в new[] и позже извлекается в delete[] для выполнения соответствующего уничтожения элементов массива. Стандартных способов доступа к этому числу также не существует.

(Это означает, что в общем случае типичный блок памяти, выделенный new[], будет независимо, одновременно хранить и физический размер блока в байтах и количество элементов массива. Эти значения хранятся на разных уровнях механизма распределения памяти C++ - raw memory allocator и new[] соответственно - и никак не взаимодействуют друг с другом).

Однако, обратите внимание, что по указанным выше причинам счетчик элементов массива обычно хранится только в том случае, если тип элемента массива имеет нетривиальный деструктор. Т.е. этот счетчик присутствует не всегда. Это одна из причин, почему предоставление стандартного способа доступа к этим данным не представляется возможным: вам придется либо хранить их всегда (что расходует память), либо ограничивать их доступность по типу деструктора (что вносит путаницу).

Для иллюстрации вышесказанного, при создании массива из ints

int *array = new int[100];

размер массива (т.е. 100) не обычно хранится в new[], поскольку delete[] не заботится об этом (int не имеет деструктора). Физический размер блока в байтах (например, 400 байт или больше) обычно хранится в блоке выделителем сырой памяти (и используется деаллокатором сырой памяти, вызываемым delete[]), но он легко может оказаться равным 420 по какой-либо специфической для реализации причине. Таким образом, этот размер практически бесполезен для вас, так как вы не сможете определить точный исходный размер массива по нему.

15
ответ дан 30 November 2019 в 04:07
поделиться

Это имеет смысл, поскольку, например, размер выделенного блока может не обязательно совпадать с размером массива. Хотя верно , что new [] может хранить количество элементов (вызывая каждый деструктор элементов), это не обязательно, поскольку это не требуется для пустого деструктора. . Также не существует стандартного способа ( C ++ FAQ Lite 1 , C ++ FAQ Lite 2 ) реализации, где new [] хранит длину массива, поскольку каждый метод имеет свою плюсы и минусы.

Другими словами, он позволяет выделять ресурсы как можно быстрее и дешевле, не указывая ничего о реализации. (Если реализация должна каждый раз сохранять размер массива, а также размер выделенного блока, она тратит впустую память, которая может вам не понадобиться).

5
ответ дан 30 November 2019 в 04:07
поделиться

Проще говоря, стандарт C ++ не требует поддержки этого. Возможно, что, если вы достаточно знаете о внутреннем устройстве вашего компилятора, вы сможете выяснить, как получить доступ к этой информации, но это в целом будет считаться плохой практикой. Обратите внимание, что может быть разница в структуре памяти для массивов, выделенных кучей, и массивов, выделенных стеком.

Помните, что по сути то, о чем вы говорите, здесь тоже массивы в стиле C - хотя new и delete являются операторами C ++ - и поведение унаследовано от C Если вам нужен «массив» C ++ определенного размера, вы должны использовать STL (например, std :: vector, std :: deque).

3
ответ дан 30 November 2019 в 04:07
поделиться

Скорее всего, вы можете получить к нему доступ, но это потребует глубоких знаний о вашем распределителе и не будет переносимым. Стандарт C ++ не определяет , как реализации хранят эти данные, поэтому не существует единого метода их получения. Я считаю, что это оставлено неопределенным, потому что разные распределители могут захотеть хранить его по-разному в целях повышения эффективности.

7
ответ дан 30 November 2019 в 04:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: