C#之CLR內(nèi)存字符串常量池(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(所以我們認(rèn)為不在堆里面)的指令,只有一個特殊ldstr(load string)指令,它用從元數(shù)據(jù)獲取一個文本常量字符串(字符串常量池)構(gòu)造一個String對象。這證明了CLR說用一種特殊的方式構(gòu)造了字符串。
我們再舉一個簡單例子看看:
class Program
{
static void Main(string[] args)
{
String s = "HelloWorld";
s = "HelloC#";
s = "HelloJava";
String s1= "HelloC#";
Console.WriteLine(s);
}
}
對照這個例子我們來看看內(nèi)存圖是怎么走的:

首先CLR內(nèi)部機(jī)制會在運(yùn)行這個方法之前就會有"prologue"代碼去開辟內(nèi)存空間,s和s1就說這個時候創(chuàng)建的。
我們創(chuàng)建了一個s的字符串對象,賦值為HelloWorld,把s插入棧,然后內(nèi)部機(jī)制去字符串常量池中找HelloWorld副本,發(fā)現(xiàn)沒有找到就會創(chuàng)建一個,接著會去保存這個HelloWorld在字符串常量池中的地址(Line1)。然后我們?yōu)閟對象在賦值為HelloC#,由于同一個對象,棧中不做操作,去字符串常量池中找,沒找到則創(chuàng)建,然后修改s所存儲的地址(line 2),HelloJava同樣的操作。 再創(chuàng)建一個s1的string對象,把s1壓入棧,為S1賦值HelloC#,這個時候會去字符常量池中找,找到了就存這個引用。
相關(guān)文章
C#反射之基礎(chǔ)應(yīng)用實(shí)例總結(jié)
這篇文章主要介紹了C#反射之基礎(chǔ)應(yīng)用實(shí)例總結(jié),包括了反射的基本原理與用法實(shí)例,需要的朋友可以參考下2014-10-10
C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途實(shí)例解析
這篇文章主要介紹了C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途,需要的朋友可以參考下2014-08-08
C#/VB.NET?實(shí)現(xiàn)彩色PDF轉(zhuǎn)為灰度PDF
本文以C#代碼為例介紹如何實(shí)現(xiàn)將彩色PDF文件轉(zhuǎn)為灰度(黑白)的PDF文件,即將PDF文檔里面的彩色圖片或者文字等通過調(diào)用方法轉(zhuǎn)為文檔頁面為灰色調(diào)、無彩色效果的文檔。快來跟隨小編一起學(xué)習(xí)吧2021-11-11

