C#中字符串的内存分配与暂存池【非常详细】

一、学会查看变量的内存地址

想要研究C#中字符串的内存分配情况,如果能查看字符串的内存地址就好了。其实我们可以在VS2017中查看变量的内存地址,截图中有详细说明: 

二、string类型简单说明

string是引用类型的,在C#中引用类型的内存分配在托管堆(堆内存)上。string不支持以下两种创建方式:

string str01 = "heng";
//错误创建方法1
string str02 = new string("heng");
//错误创建方法2
string str03 = new string(str01);

 string是System.String的别名,绝大多数情况下使用string和System.String是等效的,两者细微的区别在这里不讨论,在此处我们可以理解为两者完全一样。

三、string的不可变性(可读但不可写)

string str01="abc"和char[] charArray={'a','b','c'}是不一样的,字符串不只是简单的字符数组,他是特殊的字符数组,特殊之处是字符串的不变性,string可读但不可写,char[]可读也可写,验证过程如图:

string的不可变性验证一:

有人会说,str="999"; str+="99"; 此时str的值是"99999"。这不说明string是可更改(即可写)的吗?
下面进行string的不可变性验证二:

引用一张别人的图片来表示对string进行拼接或再次赋值时,引用的变化过程:

结论:
处理字符串一定要有变量来接收返回值,因为所有对于字符串的操作都会返回一个新的字符串,而原字符串则不受影响。 

四、string所拥有的引用类型特性

如我们所知,引用类型变量间进行赋值操作时,传递的是内存地址而不是真实值,此特性对于string同样适用;
当两个引用类型变量指向同一对象时,修改A变量的属性值,对变量B也有影响,此特性对string就不适用了,因为上边讲到当对string变量进行拼接或再次赋值时并不会改变变量所指对象的值,而是产生了新对象。

 

五、string暂存池

string作为最常用的类型,在实际项目中会有大量的字符串操作,这样会带来大量的字符串创建,内存分配、回收,进而影响性能。因此CLR对于string进行了特殊的优化,CLR中存在“字符串暂存池”概念。那么CLR 如何做到的呢?在CLR初始化时创建一个内部的哈希表,这个表相当于一个字典表,键就是字符串,值是指向托管堆中该字符串对象的引用。

Dictionary <TKey,TValue>

不是所有的字符串都放在暂存池中,以下三种情况会查询暂存池(若查询不到就将其存入暂存池):

  • 利用字面量值创建string对象
  • 利用string.Intern()创建string对象
  • 字面量值+字面量值拼接创建string对象

 下面将验证上述三种情况及其他几种常见的字符串创建情况是否会查询暂存池。

1、利用字面量值创建string对象

2、利用string.Intern()创建string对象 

3、利用ToString()创建 string对象(StringBuilder、char[])

4、利用new string()创建 string对象 

5、字符串拼接创建string对象

6、常见情况总结 

string str1 = "99999";
string str2Part = "99";
string str2 = "999" + str2Part;
object.ReferenceEquals(str1, str2); //结果是false
string str1 = $"{"999"}{"99"}";//str1等价于str2,而不是等价于str3
string str2 = "999" + "99";    
string str3 = string.format("999{0}", "99");

六、理解string暂存池

我们以前就知道C#中的有个(Intern Pool)暂存池,但当初居然认为所有的字符串都会存放在此。这几天看了书夜查了些资料才知道没那么简单。

1. 驻留池由CLR来维护,其中的所有字符串对象的值都不相同。

2. 只有编译阶段的文本字符常量会被自动添加到驻留池。

3.运行时期动态创建的字符串不会被加入到驻留池中。

4.string.Intern()可以把动态创建的字符串加入到驻留池中。

即使这个动态创建的字符串和驻留池中的某个字符串的值相等,引用也不会相等。

即使是动态创建的两个字符串的值相等,他们的引用依然不相等。(charArray.ToString()特例

整理这篇文章真是不太容易,如果本文对你有帮助,请点赞、评论支持下。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

changuncle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值