当前位置: 首页 > 科技观察

字符串是一个奇怪的引用类型

时间:2023-03-19 19:20:10 科技观察

本文转载自微信公众号《精益码农》,作者小马甲。转载本文请联系精益码农公众号。开头有两张图,内容全靠刷。看到这种现象,马甲哥先是有些疑惑。本例中string是纯引用类型,但在函数传值时类似于传值;我给出了前后例子的内存变化图:根本原因是大多数高级语言将String设计为不可变的:由一个字符串池管理字符串字面量。为什么要设计成不可变的。真的搜了这个[1]:总结一下:string被设计成不可变的,因为string在任何现代语言中都被频繁使用:多个对象可能是这个字符的字面值,然后设计一个Pool来存储细绳。由于角色面值在池中共享,修改不能影响其他人,所以只好重新复制生成新的角色面值。不可变资源杜绝了多线程中的资源竞争:文本的修改会导致创建新的空间,所以多个线程同时访问文本时不需要设置锁,对线程很友好经常使用的字符串。Stringimmutability对[在hashtables中使用stringsaskeys]是友好的,需要hash的对象必须是immutable的才能保证hash不变。一个有趣的现象是,String虽然是引用类型,但是在比较字符串时表现得像值类型stringstr1="FooFoo";stringstrFoo="Foo";stringstr2=strFoo+strFoo;returnstr1==str2;//返回true由于Stringimmutability&Pool的机制,频繁变化的字符串会在池中产生很多临时未使用的字符串,所以我们有一个优化的例程:StringBuilder代表可变字符串,一旦修改,它不会尝试创建新的字符串对象,而是动态地expandmemoryvarss=newStringBuilder("Hello",100);//初始字符容量100ss.Append("www.cnblogs.com");Console.WriteLine(ss.ToString());//ss打印结果为:222SpanSpan应该出圈了,Span提供了对连续内存区域的类型安全访问,可以位于堆,栈,甚至是非托管内存;与String的不可变性相关的是ReadOnlySpan(值类型),它提供了内存数据每个切片的只读视图,不会生成新的对象,而是在已有的连续空间上创建新的视图。vartext="https://www.cnblogs.com/JulianHuang/p/14817621.html";ReadOnlySpannameSpan=text.AsSpan(8,15);nameSpan=nameSpan.Slice(4,7);控制台。WriteLine(nameSpan.ToString());总结输出今天从两张诡异的编程图上,讲了String的不可变性和内存分布,延伸了String不可变的设计考虑(有先射箭后画靶的嫌疑??)如何实现对频繁修改的String做内存优化不是吹牛。文章内容在业界相当硬核(多次被大佬/CSDN点赞/转载)。阅读和关注不是目的,希望能得到更多的阅读反馈,促进彼此的认知提升(很诚恳??)。参考[1]我还真搜过这个:https://www.c-sharpcorner.com/UploadFile/230635/why-string-are-immutable-in-dotnet/