C#引用变量内存分配

6

有人知道创建引用类型变量时占用多少内存吗?

String s = "123";

作为引用,'s' 占用多少内存,而不是指向它的数据?


1
作为引用,'s'将占用多少内存,而不是指向它的数据?您的意思是's'作为引用将占用多少内存,而不是指向的对象? - ScottS
5个回答

11
这可以分解为以下几个部分:
String s = "123";

变量s: 这将占用当前架构上的本机指针大小(如果操作系统是32位或进程在WoW64下执行,则被认为是32位),因此相应地为32位或64位。在这种情况下,s要么在堆栈上,要么在寄存器中。如果将字符串引用放入数组中,则该空间将在堆上消耗。
字符串是一个对象的事实: 8个字节的开销分为4个字节的方法表,它同时也是对象实际类型的指示,再加上4个字节的一些管理位和同步块,使其可以作为锁定语句的目标。
字符串始终以空字符终止(尽管这是运行时的实现细节而不是合同的一部分),以便可以直接与C风格的字符串API一起使用,字符是UTF-16,因此每个字符在.NET使用字符时需要两个字节(为什么的细节很复杂,需要涉及Unicode,我将省略)。
字符串还包含以下内容:
.Net 4.0之前的版本
  • 一个int表示字符串的字符长度
  • 一个int表示容纳字符的底层数组的长度
  • 一个字符,它是字符串中的第一个字符(后续字符直接跟在它后面),或者对于空字符串是空字符
字符串可能会因StringBuilder的工作方式而占用高达所需字符数组的两倍的内存。
因此,字符串本身将在堆上消耗16 +(2 * n)+ 2到16 +(4 * n)+ 2个字节之间的空间,具体取决于它是如何创建的。

.Net 4.0及以上版本

  • 一个整数表示字符串的字符长度
  • 一个字符代表字符串中的第一个字符(后续字符紧跟其后),或对于空字符串,一个空字符。

该字符串在堆上至少占用12 + (2*n) + 2字节。


请注意,在这两种情况下,字符串可能会占用略微更多的实际空间,具体取决于运行时强制执行的对齐方式,这很可能不超过IntPtr.Size。
这可能会因字符串内部化而变得更加复杂(两个独立实例最终指向同一个字符串,因为它是不可变的),因为理论上应该将堆开销(加上内部开销)除以对字符串的“独立”引用数。
要了解更多讨论,请查看此文章。但请注意,此文章已过时,不适用于4.0中的更改。

10

参考本身的大小取决于您的处理器架构 - 32位为4字节,64位为8字节。


+1,或者更恰当的答案是:一丁点儿重要空间。 - user7116
你有这方面的文档参考吗? - AnthonyWJones
不具权威性,但可以尝试使用http://msdn.microsoft.com/en-us/magazine/cc163791.aspx。 .Net引用在内部只是指向托管堆上对象的指针。 - Stu Mackellar
ECMA-335(公共语言基础设施):12.1 支持的数据类型。它们存储在一个等于指针大小的本机大小整数中。 - user7116
请注意,这取决于处理器架构、操作系统位数以及可执行文件是否支持在64位模式下运行。 - ShuggyCoUk
好的一点是,32位可执行文件在WOW64下运行时仍将具有4字节的引用大小。 - Stu Mackellar

4

根据您的计算机是32位还是64位,指针将是32位或64位。


不行。为什么?你如何以更节省的方式引用内存中的对象? - mqp
安东尼是正确的。在32位机器上,指针是32位的。而在64位机器上则为64位。你可能会因为从位到字节的转换而感到困惑。 - masfenix

1

通常需要4个字节的引用


1
如果您想在代码中进行检查,请调用以下代码:
IntPtr.Size

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接