再次加强对于栈和堆的内存的理解---string的故事
要多站在编程语言设计者的角度,去理解编程语言
还有就是要是有能力的话,可以同时再学学别的小一点的语言,
可以互相融汇贯通
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//字符串-池的概念
//字符串的不可变性就在于此
string s1 = "你好";
string s2 = "你好";
//用于比较两个地址是否相同
bool r1 = object.ReferenceEquals(s1,s2);//true
string s3 = new string(new char[] { '再','见'});
string s4 = new string(new char[] { '再', '见' });
bool r2= object.ReferenceEquals(s3, s4);//false
/*
* string 特殊的机制,提高字符的利用率
* s1 是直接创建字符串,没有“你好”这两个字符,放在池子里
* s2去检查池子里有没有这两个字符,有的话直接返回“你好”字符串的引用
* 没有的话就开辟空间存储新的字符串
* s1和s2也可以叫字符串常量,直接写死
* s3和 s4 用了new关键字,显然重新开辟了空间
* 所以s3和s4对比的结果就是false
*
*/
s1 = "hello";
//并不是将文本“你好”改成了“hello”,
//而是在字符串-池里重新开辟空间增加新的字符串
//替换栈中的引用
//为什么不能改呢??????????
// 首先hello 或者其他的字符串大小不一定相等
//并且内存空间是连续的,会覆盖后面有用的数据,导致内存泄漏
//所以每次都要开辟新的,改变数据的引用
//祖师爷的智慧,避免这种问题。程序设计者的思维很有趣吧
//下面的代码每次修改都是重新开辟新的 空间
object o1 = 1;
o1 = 2.0;
o1 ="OKsasdasd是否 ";
o1 = true;
//自己推断一下,就能推断出来
//字符串经常频繁的拼接
/*
* ""+"0"
* "0"+"1"
* "01"+"2" 每次拼接产生新的对象,替换引用
* 原有的数据就变成了垃圾
* 所以字符串拼接一定不要用下面的 方式,太浪费性能,造成很多垃圾
* 0.02秒就拼一次
*/
string strNum = "";
for (int i = 0; i < 10; i++)
{
strNum += i.ToString();
}
Console.WriteLine(strNum);
//那怎么解决呢?
//k可变字符串,性能好很多
//会直接在堆上开发一个大块的空间,用于append数据
//参数是建议的空间大小
StringBuilder builder = new StringBuilder(10);
for (int i = 0; i < 10; i++)
{
builder.Append(i);
}
string result = builder.ToString();
builder.Append("还能继续增加数据");
//为什么可以呢?不是说内存是连续的吗?
//具体方式是开辟一个更大的新的内存空间,将原来的数据整体搬过去
//将栈上的引用也替换成新的引用
//原来的变成了垃圾,给回收,相对来说这种方式好很多
//builder的很多功能,类似Python的string的自带功能增删改查的功能