C#之CLR內存字符串常量池(string)。本站提示廣大學習愛好者:(C#之CLR內存字符串常量池(string))文章只能為提供參考,不一定能成為您想要的結果。以下是C#之CLR內存字符串常量池(string)正文
C#中的string是比特別的類,說援用類型,但不存在堆外面,並且String str=new String("HelloWorld")如許的重裝也說沒有的。
我們先來看一個辦法:
class Program { static void Main(string[] args) { String s = "HelloWorld"; Console.WriteLine(s); } }
然後我們用ildasm.exe對象把它生成IL說話來看一看它外面是怎樣玩的:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 15 (0xf) .maxstack 1 .locals init ([0] string s) IL_0000: nop IL_0001: ldstr "HelloWorld" IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: call void [mscorlib]System.Console::WriteLine(string) IL_000d: nop IL_000e: ret } // end of method Program::Main
我們在外面並沒有看見newObj(所以我們以為不在堆外面)的指令,只要一個特別ldstr(load string)指令,它用從元數據獲得一個文本常量字符串(字符串常量池)結構一個String對象。這證實了CLR說用一種特別的方法結構了字符串。
我們再舉一個簡略例子看看:
class Program { static void Main(string[] args) { String s = "HelloWorld"; s = "HelloC#"; s = "HelloJava"; String s1= "HelloC#"; Console.WriteLine(s); } }
對比這個例子我們來看看內存圖是怎樣走的:
起首CLR外部機制會在運轉這個辦法之前就會有"prologue"代碼去開拓內存空間,s和s1就說這個時刻創立的。
我們創立了一個s的字符串對象,賦值為HelloWorld,把s拔出棧,然後外部機制去字符串常量池中找HelloWorld正本,發明沒有找到就會創立一個,接著會去保留這個HelloWorld在字符串常量池中的地址(Line1)。然後我們為s對象在賦值為HelloC#,因為統一個對象,棧中不做操作,去字符串常量池中找,沒找到則創立,然後修正s所存儲的地址(line 2),HelloJava異樣的操作。 再創立一個s1的string對象,把s1壓入棧,為S1賦值HelloC#,這個時刻會去字符常量池中找,找到了就存這個援用。