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#,這個時刻會去字符常量池中找,找到了就存這個援用。