简单看看这两个类 String和StringBuilder
我记得以前在园子里面讨论这两个类的文章有很多很多,并且还拿出了很多的测试报告,在什么情况下,谁比谁快,在什么情况下,该用谁
不该用谁等等这些,我这里就不比较了,我就简单看看他们里面的内部实现,那就先看看String吧。
一:String类
说到String类,资料上都说是存在于堆上的一个不可CURD的一个不可变的字符集,当然看到这句话之后就想要看看是不是这样的,然后就
好奇的写了以下代码。
class Program
{
static void Main(string[] args)
{
string s = "";
}
}

从上面的IL中也就仅仅发现一个ldstr指令,看得出clr把string做成了基元类型,也就没看到它具体转换成了什么样的方法,是不是调用了string
的构造函数,这个也不清楚,也就不知道具体怎么把这个有序字符集放到堆中,不过办法还是有的,我们随便挑一个方法看看,比如简单一点的
substring,我们看看它的源代码。

然后我们找到了一个核心的方法,这个internalSubstring里面定义了两个指针ptr和ptr2,ptr则指向新申请的内存块的首地址,ptr2则指向原始
字符串的首地址,最后将ptr2的位置偏移startindex个位置,最后我们就找到了终极方法string.wstrcpy。

在string.wstrcpy方法里面,虽然看的迷迷糊糊,不过还是能看到类似这样的偏移操作,一点一点的将smem地址上的字符赋值给dmem中,
确实也就说明了在堆上是有序的字符集。

同样在上面的源代码中来说,substring操作并没有对原始字符串进行修改,而是把截取的值放到新申请的内存地址空间中,这也就说明了字符
串是不可修改的说法,当然如果设计者真的要做到原位修改,那肯定也是能做到的,为了佐证下,我再举一个经常用到的concat方法,不过在
FastAllocateString方法中,并没有看到他的源代码,所以只能说根据length申请合适的空间。

所以结论出来了: 当你对字符串进行大量操作的时候,会产生很多的新的字符串,这些字符串会大量零碎的占据着堆空间,大多都是生存期较短
的,所以一般都是在堆的第一代上,所以会对gc产生了比较大回收压力。
二:StringBuilder
看这个类的话,还是看一下它的源代码,就抽一个Append吧,从下面这个截图中看出来几个有意思的地方。
<1> 原来StringBuilder里面维护的是一个m_ChunkChars的字符数组。
<2> 如果当前的字符串的length<2,会直接给chunkchars数组复制,length>2的时候看到的是刚才string类中经典的wstrcpy用法,而
这个时候ptr指向的是chunkChars[chunkLength]的首地址,而不像string中申请新的内存空间,所以从这里看,比string大大的节省
了内存空间。

好了,具体他们的性能比较我也不说了,大家看着他们的原理凑合着用吧,简单的看看也只能看到这了,再看就漏点了。
简单看看这两个类 String和StringBuilder的更多相关文章
- Reader与InputStream两个类中的read()的区别
InputStream类的read()方法是从流里面取出一个字节,他的函数原型是 int read(); ,Reader类的read()方法则是从流里面取出一个字符(一个char),他的函数原型也是 ...
- C#基础知识系列三(类和结构体、String和StringBuilder、equals和==)
前言 这一节主要来了解一下类和结构体之间的异同点.以及针对String和StringBuilder的用法.equals和==,其实可以看出很多地方都用到了上一节的值类型和引用类型.堆栈和装箱拆箱操作吧 ...
- 深入理解Java常用类----String
Java中字符串的操作可谓是最常见的操作了,String这个类它封装了有关字符串操作的大部分方法,从构建一个字符串对象到对字符串的各种操作都封装在该类中,本篇我们通过阅读String类的源码 ...
- 通过反射实现Microsoft Visual Studio International Pack 1.0 SR1里面的两个类
这两天打算实现拼音和简繁转换的方法, 发现Microsoft Visual Studio International Pack 1.0 SR1 提供了 . 下载地址 但是基于某些原因, 一来下载 ...
- 重温java中的String,StringBuffer,StringBuilder类
不论什么一个系统在开发的过程中, 相信都不会缺少对字符串的处理. 在 java 语言中, 用来处理字符串的的类经常使用的有 3 个: String.StringBuffer.StringBuilder ...
- 关于String和StringBuilder、StringBuffer的一个简单性能测试
String a=String b + String c + String d 这种代码在程序里应该随处可见,一部分人不知道这段代码的缺陷在哪,另一部分人知道这样写不好,但是太顺手了下意识就写了. 在 ...
- 【转】Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)
本篇文章主要介绍了"Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)",主要涉及到Unity3D 场景切换与持久化简单数据储存(PlayerPrefs类)方 ...
- 使用redis-py的两个类Redis和StrictRedis时遇到的坑
使用redis-py的两个类Redis和StrictRedis时遇到的坑 前言: 今天产品经理说,有几个队列排序的功能不能用了.对比了下以前的代码查到了一个原因,这个比较的坑,总结起来也是自己没好好看 ...
- 手写一个HTTP框架:两个类实现基本的IoC功能
jsoncat: 仿 Spring Boot 但不同于 Spring Boot 的一个轻量级的 HTTP 框架 国庆节的时候,我就已经把 jsoncat 的 IoC 功能给写了,具体可以看这篇文章&l ...
随机推荐
- 修复 XE7 update1 发布 iOS 8.x 实机问题
1. 开启工程目录下面的 Entitlement.TemplateiOS.xml 档案. 2. 加入二行: <key>application-identifier</key> ...
- Git submodule 特性
当你习惯了代码的 VCS 后,基本上是离不开的. 作为一个依赖多个子项目组成的项目,要实现直观的代码逻辑结构,可以考虑使用 Git submodule 特性. 当然,如果只是单独的依赖的话,用依赖管理 ...
- AngularJS的ng-click传参
<ul id="dataSet" ng-repeat="item in infos" ng-model="dataSet"> & ...
- iOS AFNetworking 打印从服务器返回的错误提示信息
每次做项目的时候都会在网络请求时候测试接口的时候会出现一些不同的错误,而控制台打印的错误提示信息都是data类型,看不出提示的错误的信息是什么.后面经过一些查阅发现其实是可以把这个转变为string的 ...
- Spring中的事务
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...
- Fiddler (五) Mac下使用Fiddler
Fiddler是用C#开发的. 所以Fiddler不能在Mac系统中运行. 没办法直接用Fiddler来截获MAC系统中的HTTP/HTTPS, Mac 用户怎么办呢? Fiddler可 ...
- rabbitmq批量删除队列
有些时候,我们需要批量的删除rabbitmq中的队列,尤其是对于那些客户端配置了队列不存在时自动创建,但断开时不自动删除的应用来说. rabbitmqctl并没有包含直接管理队列的功能,其提供的vho ...
- C# 如何在Excel 动态生成PivotTable
Excel 中的透视表对于数据分析来说,非常的方便,而且很多业务人员对于Excel的操作也是非常熟悉的,因此用Excel作为分析数据的界面,不失为一种很好的选择.那么如何用C#从数据库中抓取数据,并在 ...
- Java2_J2EE、J2SE和J2ME的区别
解析J2EE.J2SE.J2ME.JDK的区别 本文向大家简单介绍一下JDK.J2EE.J2SE.J2ME概念及区别,J2EE,J2SE,J2ME是java针对不同的的使用来提供不同的服务 ...
- go语言 类型:布尔类型
Go语言中的布尔类型与其他语言基本一致,关键字也为bool,可赋值为预定义的true和false示例代码如下: var v1 bool v1 = true v2 := (1 == 2) // v2也会 ...