Как хранится массив структур?
Как хранятся данные массив структур и классов. То есть, массив это ссылочный тип, а структура значимый, то есть хранится в стеке. И еще массивы структур в бенчмарке занимают место в куче, хотя не должны, ведь они должны храниться в стеке. Куда ссылаются ссылки массива? И тем же макаром объясните массив классов.
Ответы (2 шт):
Вы просто запутались, распутаться легко.
Значимый тип - это кусок памяти с данными, например int это 4 байта, представляющие число. int это структура. Для массива интов CLR выделяет N * 4 байт памяти.
Ссылочный тип состоит из 2 частей: ссылка и сам объект. Ссылка - это тот же по сути int, те же правила, значимый тип. Разница только в том что тип IntPtr, который используется для ссылок в 32-битных приложениях имеет размер 4 байта, а в 64-битных - 8 байт.
То есть грубо говоря массив любых ссылочных объектов object[] это мехнически ни что иное, как IntPtr[]. Другими словами, массив хранит только ссылки и тип для этих ссылок в своих метаданных. Сам же тип данных в массиве никак не влияет на его поведение. Любой [] массив хранит данные только в куче.
Утверждение, что значимые типы могут храниться только в стеке неверно, они могут храниться и в стеке и в куче, здесь нет никаких ограничений.
Вопрос только в том, будет память выделена заранее в стеке сразу или она будет выделена по необходимости еще одним дополнительным обращением к системе за ресурсами.
Смотрите на исходный тип самой переменной. Если он значимый - значит память заранее выделится и будет лежать в стеке как значение. Если он ссылочный, то память выделится ровно под ссылку, заполнять вы её будете отдельным обращением за ресурсами.
Переменная для массива ссылочная - значит память выделится под ссылку, сам массив отдельным запросом. Создали массив - какие в нём переменные будут? Если значимые, значит массив со значениями. Если ссылочные - значит массив ссылок и всё остальное опять же отдельным запросом к системе.
Понимать это надо только для того, что считать время и потребляемую память. Каждое значение на стеке это плюс память. Каждое значение в куче это плюс время за запрос ресурсов у системы.
А дальше вы уже можете играть в матрешку, создать объект в котором есть структура, у которой есть ссылка на объект, у которой есть структура и т.д. Опять же единственный вопрос, будет ли память выделена сразу под данные или только под ссылку (а данные уже отдельно запрашиваются по необходимости).
struct StackMemory
{
public HeapMemory heap;
}
class HeapMemory
{
public StackMemory stack;
}
class Program
{
StackMemory stack;
private void Run()
{
stack.heap = new HeapMemory();
stack.heap.stack.heap = new HeapMemory();
stack.heap.stack.heap.stack.heap = new HeapMemory();
}
static void Main(string[] args) => new Program().Run();
}
Запросили new HeapMemory() - место под StackMemory выделилось сразу с запросом в котором только место под ссылку на следующую HeapMemory. И так по кругу. Еще учитывайте, что это примерное поведение, на самом деле программа не обязана вам сразу выделять память в стеке и спокойно может хранить его где-то в куче.