String是一个奇怪的引用类型

简介: 今天从两张诡异的编程图聊到了String的不可变性、内存分布, 延伸谈到了String不可变性的设计设计考量(有先射箭再画靶的嫌疑☺️)针对频繁修改的String如何做内存优化

开局两张图,内容全靠刷。


df7e016b8b9928349d6499287181afb7.png


bc53cf357f11fd484c3beb56bd0beaf0.png


马甲哥看到这样的现象,一开始还是有点懵逼。


这个例子,string是纯粹的引用类型,但是在函数传值时类似于值传递;我之前给前后示例的内存变化图吧:


7c5f07437f2aeb2b70975529e46355e9.png


根因就是大多数高级语言都把String设计成不可变的: 由一个字符串池管理字符串面值。


为什么被设计成不可变。


这个我还真的搜索了一下[1]


总结起来:


  1. string 被设计为不可变, 是因为 string在现代任何语言中,使用很频繁:多个对象可能都是这个字符面值, 然后就设计一个Pool来存储string。既然pool里面共享字符面值,修改的时候又不能影响到别人,那就只好重新拷贝产生新的字符面值。


  1. 不可变资源消除了多线程中的资源竞争:对于文本的修改都会导致创建新空间,因此在多个线程同时访问文本无需设置锁,这对高频使用的String很友好。


  1. 字符串不变性对于[在哈希表中使用字符串作为键]很友好,需要计算哈希值的对象必须是不可变的,以确保哈希值不变。


  • 一个有意思的现象是:String虽然是引用类型,字符串对比时却表现的像值类型


string str1="FooFoo";
string strFoo="Foo";
string str2= strFoo + strFoo;
return str1 == str2;           //  返回true


正因为String不可变性 & Pool的机制,频繁变更字符串,会在池中产生很多临时的不用的字符串,所以我们有了优化的套路:


StringBuilder


代表可变的字符串,一旦修改不会尝试创建新对象,而是动态扩展内存


var ss = new StringBuilder("Hello ", 100);  // 初次字符容量100
ss.Append("www.cnblogs.com");
Console.WriteLine(ss.ToString());  // ss打印结果为:222


c75d719a98f68eab826467aa17330147.png


Span


Span该出圈了,


Span提供对内存连续区域的类型安全访问,该内存可以位于堆、堆栈、甚至是非托管内存;


与String不可变性相关的是ReadOnlySpan(值类型), 提供内存数据的只读视图,每次切片不会产生新对象,而是在已存在的连续空间上创造新的视图。


var text = "https://www.cnblogs.com/JulianHuang/p/14817621.html";
ReadOnlySpan<char> nameSpan = text.AsSpan(8, 15);
nameSpan = nameSpan.Slice(4,7);
Console.WriteLine(nameSpan.ToString());



07a31e57c712f52e13e2dbcfb73cfcf0.png


总结输出


今天从两张诡异的编程图聊到了String的不可变性、内存分布, 延伸谈到了


  1. String不可变性的设计设计考量(有先射箭再画靶的嫌疑☺️)


  1. 针对频繁修改的String如何做内存优化
目录
打赏
0
0
0
0
11
分享
相关文章
基本类型、包装类型、引用类型、String等作为实参传递后值会不会改变?
基本类型、包装类型、String类型作为参数传递之后,在方法里面修改他们的值,原值不会改变!引用类型不一定,要看是怎么修改它的。
268 0
前端祖传三件套JavaScript的对象之常用引用类型的String
字符串是 JavaScript 中最常用的数据类型之一,作为 JavaScript 的基础之一,它拥有一系列的函数和方法,可以方便地完成各种字符串操作。在本文中,我们将深入探讨 JavaScript 字符串的对象类型,并介绍其中一些常用的引用类型。
144 0
C# string特殊引用类型
一、string的确是引用类型 常规上是这样定义的:     string是引用类型,但是其又具有值类型的一些特性。   static void Main(string[] args) ...
915 0
string 是值类型,还是引用类型(.net)
一. string 类型的用法比较像值类型 稍微有点.NET 编程知识的人都知道 string是引用类型。我为什么还有此一问?因为string的使用非常像值类型。举个例子: string str = "abc"; Test(str); MessageBox.Show(str); private void Test(string str) {      str = str + "de"; }   运行上面的代码你会发现 str始终是abc,这就有点像值类型。
1039 0
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
37 0
|
4月前
|
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
116 11
|
4月前
|
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
111 9
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
240 2
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问