Сколько памяти использует пустой указатель?
В С#, если я использую следующий код
Dictionary<int,object> dictionary = new Dictionary<int, object>();
dictionary.Add(1,null);
dictionary.Add(2,new object());
dictionary[2] = null;
Сколько памяти выделяется?
каждая ссылка на объект в словаре (словарь [1], словарь [2]) принимает размер указателя (32 или 64 бит) в куче? другими словами, когда я делаю словарь .Add(1, null), CLR автоматически создает 2 распределения в куче, один для int и один для нулевого указателя?
Ответы
Ответ 1
Нулевой указатель не выделяет никакой дополнительной памяти для хранения чего-либо в куче (поскольку хранить нечего). Однако ваш словарь должен хранить нулевой указатель, который занимает столько же места, сколько и любой другой указатель.
Будет ли каждый добавочный вызов получать новые распределения (для хранения указателя) или нет, зависит от реализации словаря. Обычно он имеет внутренний массив, который при необходимости изменяется по размеру.
В вашем примере я бы предположил, что достаточное пространство для нескольких элементов уже выделено при создании словаря. Таким образом, add (1, null) не будет выделять больше места.
Обновление: начальная емкость по умолчанию для словаря не указана. В .NET 4.0 он начинается с 0, фактически, поэтому первое добавление создаст массив хранения.
Ответ 2
Сам по себе нулевой указатель будет занимать 4 или 8 байт, в зависимости от того, работает ли он как 32-разрядный или 64-разрядный, как вы предполагали.
В данной коллекции может быть больше. Реализация Dictionary<TKey, TValue>
использует как массив структур Entry<TKey, TValue>
, который содержит два int
, так и ключ и значение, а также массив целых чисел, используемых при индексировании в этот массив. Следовательно, даже если бы не было "растущей комнаты" (и, как правило, каждая), для каждой записи понадобилось бы 20 байт или 24 байт памяти (а не только 8 или 12 по величине ключа и значения) поверх накладных расходов для самого словаря (включая накладные расходы каждого массива).
Другие реализации и другие коллекции будут иметь другие накладные расходы. Они могут даже не хранить null
для нулевой записи. null
может быть полезным способом указания значения, которое не было записано, в этом случае специальное значение будет указывать фактическое значение null
(особенно полезно в реализациях без блокировки словаря, где может быть полезно различать не просто сброшенное и установленное значение, но между неустановленным, установленным и частично установленным значением).
Все, что вы действительно можете сказать, это то, что параметр добавления значения null
A) занимает некоторую память, а B) не занимает память, которая с ненулевым значением будет восприниматься самим объектом. Даже B) на самом деле не выполняется, поскольку, если этот объект также был сохранен в другом месте, тогда нет никакой дополнительной стоимости памяти при наличии другой ссылки в другом месте, помимо ссылки самой ссылки, что делает реальную стоимость ее такой же, как хранение null
.
Ответ 3
Я думаю, да, потому что null является ссылкой. Он указывает на ниоткуда, но вы можете каждый раз заменять его реальной ссылкой на объект.
Итак, я предполагаю, что выделено не менее 2x64 бит, возможно, словарь нуждается в дополнительном пространстве для себя.