Как распределяется массив типов значений в куче? - PullRequest
0 голосов
/ 20 сентября 2018

Я прочитал ответ на некоторые из подобных вопросов, но мой вопрос немного отличается из-за того, что я не понимаю утверждения, написанного об этом в книге.

Поскольку структура - этотип значения, каждый экземпляр не требует создания экземпляра объекта в куче;это приносит полезную экономию при создании многих экземпляров типа.Например, для создания массива типа значения требуется только одно выделение кучи.

Я имею в виду Как массиву может потребоваться только одно выделение кучи? ... или что это означает под выделением одной кучи

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Прежде всего, давайте уточним, что мы подразумеваем под «кучей» против «стека».

Большинство современных сред программирования основаны на стеке.Когда вы запускаете программу, каждый раз, когда вы вызываете метод, новая запись помещается в специальный стек, предоставленный для вашей программы.Эта запись стека (или фрейм) сообщает системе, где искать исполняемый код метода, какие аргументы были переданы и куда именно возвращаться в вызывающем коде после выхода из метода.Когда метод завершается, его запись удаляется (выталкивается) из стека, поэтому программа может вернуться к предыдущему методу.Когда стек пуст, программа завершена.

Каждый кадр в стеке также имеет определенное количество места для локальных переменных для метода, а сам стек имеет ограниченный размер.Отсюда и «переполнение стека».Получите слишком много вызовов методов, стеку не хватит места.

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

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

Теперь, когда мы это много понимаем, мы можем начать смотреть на массивы.

Тип базового массива сам по себе является ссылочным типом. Я имею в виду, что для любого данного типа T, T может быть (или не быть) типом значения, но T[]всегда является ссылочным типом.В контексте «стек против кучи» это означает, что создание нового массива является выделением кучи, даже если T является типом значения.Массивы также имеют фиксированный размер.Это одиночное выделение кучи создаст достаточно места для всех элементов в массиве.

Дополнительной особенностью типов значений является то, что они имеют фиксированный размер, основанный на элементах.Таким образом, для массива у нас есть фиксированное количество элементов, каждый с известным фиксированным размером.Этого достаточно, чтобы получить все пространство для объекта массива и его элементов в одном выделении кучи.Значение каждого элемента хранится в памяти ядра массива.

Для массива, содержащего ссылочные типы, выделение кучи для массива создает пространство только для ссылок .Чтобы заполнить массив, вы должны сделать дополнительные выделения для каждого элемента.

Это может быть немного осложнено типом значения с одним или несколькими членами ссылочного типа.В этой ситуации пространство для типа значения выделяется как обычно, но часть значения для ссылочных элементов является просто ссылкой.Для создания объектов для этих ссылочных членов по-прежнему требуются отдельные выделения.

0 голосов
/ 20 сентября 2018

Массив сам по себе является ссылочным типом, что означает, что он размещен в управляемой куче.Но если это массив типа значения, он резервирует память, необходимую для его размера, за один шаг.Позволяет вам иметь структуру с 4 Int32 в нем.

A struct4Int[1000] will allocate 16000 bytes in one step.

Массив ссылочного типа займет только память, необходимую для ссылок (32 или 64 бит на элемент, в зависимости от архитектуры, для которой вы компилируете).Скажем, класс с 4Int32 в нем.

A class4Int[1000] will allocate 4000 or 8000 bytes at first.

Элементы заполняются адресом ссылок, который по существу равен нулю.

После создания массива вам нужно будет выделить память для каждого экземпляра ссылочного типа и поместитьэто ссылка на массив (несколько выделений в куче), добавление еще 16000 байтов в кучу в 1000 маленьких кусочков.

...