【发布时间】:2010-11-25 18:17:59
【问题描述】:
int (Int32) 的内存占用为 4 个字节。但是什么是内存占用:
int? i = null;
和:
int? i = 3;
这是一般情况还是取决于类型?
【问题讨论】:
-
在任何情况下,你是否有一个值,或者它是“null”都没有关系。无论如何,它将占用相同数量的字节。
int (Int32) 的内存占用为 4 个字节。但是什么是内存占用:
int? i = null;
和:
int? i = 3;
这是一般情况还是取决于类型?
【问题讨论】:
我不是 100% 确定,但我相信它应该是 8 个字节,int32 应该是 4 个字节,并且(因为在 32 位机器上每件事都必须是 4 字节对齐)另外 4 个字节作为布尔值表示是否指定了整数值。
注意,感谢@sensorSmith,我现在知道 .Net 的较新版本允许可空值存储在更小的占用空间中(当硬件内存设计允许独立分配更小的内存块时)。在 64 位机器上,它仍然是 8 字节(64 位),因为这是可以寻址的最小内存块......
例如,可为空的布尔值只需要一个位,IsNull 标志需要另一个位,因此总存储要求小于一个字节,理论上它可以存储在一个字节中,但是,像往常一样,如果可以分配的最小内存块是 8 字节(如在 64 位机器上),那么它仍将占用 8 字节内存。
【讨论】:
sizeof(bool) 返回 1,因此 Nullable<Int32> 将占用 5 个字节。我不认为填充添加到结构的末尾。
Nullable<T> 的大小绝对取决于类型。该结构有两个成员
结构的大小通常会映射为 4 加上类型参数 T 的大小。
【讨论】:
似乎第一个 dword 是值,第二个是空标志。所以,总共 8 个字节。
很好奇,BinaryWritter 不喜欢编写可为空的类型。我在徘徊,如果它可以将它压缩到 8 个字节......
【讨论】:
.NET(和大多数其他语言/框架)的默认行为是将结构字段与其大小的倍数对齐,并将结构自身与其最大字段大小的倍数对齐。参考:StructLayout
Nullable<T> 有一个 bool 标志和 T 值。由于 bool 只占用 1 个字节,因此最大字段的大小是 T 的大小;与单独的 T 相比,Nullable 所需的空间增加了一倍。参考:Nullable Source
澄清:如果 T 本身是一个非原始结构而不是原始类型,Nullable 会根据 T 内的最大原始字段的大小增加所需的空间,或者递归地增加任何 T 内的空间非原始字段。所以,Nullable<Nullable<bool>> 的大小是 3,而不是 4。
【讨论】:
您可以使用类似于https://www.dotnetperls.com/nullable-memory 的代码进行检查。
我得到了以下结果:
Int32 4 个字节Int32? 8 个字节Int16 2 个字节Int16? 4 个字节Int64 8 个字节Int64? 16 字节Byte 1 个字节Byte? 2 个字节bool 1 个字节bool? 2 个字节【讨论】:
int? 是一个包含布尔值 hasValue 和 int 的结构。因此,它的占用空间为 5 个字节。这同样适用于 nullable<T> 的所有实例:size = sizeof(T)+sizeof(bool)
【讨论】:
可空类型是包含常规变量和空状态标志的结构。
对于一个可为空的 int,这意味着它包含五个字节的数据,但它当然会被填充到完整的单词中,因此它使用了八个字节。
您通常可以预期任何可为空的类型都将比常规类型大四个字节,字节和布尔等小类型除外。
【讨论】:
32 位和 64 位机器:
可空类型包装器需要 4 个字节的存储空间。和整数 每个元素本身需要 4 个字节。这是一个高效的 执行。在一个数组中,许多可为空的类型存储在 连续内存。
基于个人测试(.NET Framework 4.6.1、x64、Release)并来自 – https://www.dotnetperls.com/nullable-memory
另外,如果感兴趣的话:why int on x64 equals only 4 bytes?
注意:这仅对Nullable<int>有效,Nullable<T>的大小完全取决于类型。
【讨论】: