簡單看看這兩個類 String和StringBuilder


  我記得以前在園子里面討論這兩個類的文章有很多很多,並且還拿出了很多的測試報告,在什么情況下,誰比誰快,在什么情況下,該用誰

不該用誰等等這些,我這里就不比較了,我就簡單看看他們里面的內部實現,那就先看看String吧。

 

一:String類

  說到String類,資料上都說是存在於堆上的一個不可CURD的一個不可變的字符集,當然看到這句話之后就想要看看是不是這樣的,然后就

好奇的寫了以下代碼。

1     class Program
2     {
3         static void Main(string[] args)
4         {
5             string s = "123";
6         }
7     }

 

從上面的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大大的節省

    了內存空間。

 

好了,具體他們的性能比較我也不說了,大家看着他們的原理湊合着用吧,簡單的看看也只能看到這了,再看就漏點了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM