字符串生成器的内存分配。记忆中会发生什么? StringBuilder与String

时间:2016-05-12 11:05:16

标签: c# memory memory-management

可能是副本,因为关于这个主题有很多问题,但我无法找到我想要的东西。 我知道String是不可变的,StringBuilder是可变的。我理解这两个术语的本质。我想知道在创建StringBuilder的实例时内存中究竟发生了什么。像:

StringBuilder s = new StringBuilder();
  1. 内存中为s保留了多少空间?
  2. 我可以像s[0] = 'a';一样使用它,所以我们可以称之为数组吗?
  3. 如果s是基于索引的那么意味着字符存储在连续位置的内存中?
  4. 如果回答3是肯定的。那么如果我们使用s.appennd("abc");并且内存中没有"abc"足够的连续空间会发生什么?每次我向s类型变量附加内容时,string会发生string新内存位置。

2 个答案:

答案 0 :(得分:4)

StringBuilder实际上是在引擎盖下,StringBuilders链(将它们视为连锁的记忆块)。用户显然正在与一个StringBuilder进行交互,但这远非如此。

每个StringBuilder使用基础char数组,当容量耗尽时,新的StringBuilder将添加到链中。

记住这一点,您的具体问题的答案将是:

  1. 查看实现以查看StringBuilder的默认容量以及它的底层数组是什么。您还可以使用构造函数重载来指定它,以满足您的特定需求。
  2. 是的,引擎盖下的StringBuilder使用数组,但链中的每个构建器都有自己的数组。
  3. 是和否。链中每个内部构建器的数组的内存是连续分配的,但不需要不同的内存块,并且很可能不会连续分配。
  4. 当没有足够的空间时,将 new StringBuilder添加到链中,并在运行时认为合适的任何地方分配相应的数组;通常,新构建器将至少使StringBuilder的总容量加倍,并且新阵列很可能不会连续分配到前一个阵列。
  5. 显然,这个系统允许动态调整大小,同时避免与调整数组大小和来回复制数据相关的成本。

答案 1 :(得分:0)

StringBuilder允许分配非连续内存以提供单个连续字符串的感知。我在内部相信它是一组指向字符串片段的指针,当你调用" ToString"时会重新组合它们。数组索引的处理只是数学的一个包装。当你.Append()它只是抓取一个新内存块并将字符串片段放在其中,维护片段及其长度的索引列表