字符串不可變性是通過語句還是通過語句中的字符串工作?字符串不可變性
例如,我知道下面的代碼會在堆上分配兩個字符串。
string s = "hello ";
s += "world!";
「hello」將留在堆上直到垃圾收集;現在引用「你好世界!」在堆上。但是,下列行在堆上分配了多少個字符串... 1或2?另外,有沒有一種工具/方法來驗證結果?
string s = "goodbye " + "cruel world!";
字符串不可變性是通過語句還是通過語句中的字符串工作?字符串不可變性
例如,我知道下面的代碼會在堆上分配兩個字符串。
string s = "hello ";
s += "world!";
「hello」將留在堆上直到垃圾收集;現在引用「你好世界!」在堆上。但是,下列行在堆上分配了多少個字符串... 1或2?另外,有沒有一種工具/方法來驗證結果?
string s = "goodbye " + "cruel world!";
編譯器提供了字符串連接,這是特殊待遇,爲什麼第二個例子是隻有永遠一個字符串。而「實習」意味着即使你運行這一行20000次,仍然只有1個字符串。
重新測試結果...最簡單的方法(在這種情況下)可能是反射鏡看:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] string s)
L_0000: ldstr "goodbye cruel world!"
L_0005: stloc.0
L_0006: ldloc.0
L_0007: call void [mscorlib]System.Console::WriteLine(string)
L_000c: ret
}
正如你可以看到(ldstr
),編譯器已經做了這個給你。
如果編譯器是「智能」的,它只會是一個帶有「再見殘酷的世界!」的字符串!
它是,它確實如此。在我的回覆中看到IL。 – 2008-12-16 19:25:40
也做一個谷歌實習生池 – JamesSugrue 2008-12-16 19:29:27
實際上,可能是3.「goodbye」的常量字符串,「殘酷世界」的const字符串,然後是結果的新字符串。
您可以通過查看生成的代碼來確定。它依賴於編譯器(事實上,這在語言中並不明顯),但是你可以通過使用-a標誌(我認爲,檢查手冊頁)來讀取g ++的輸出以獲得中間代碼。
這是.net他要求。 – 2008-12-16 19:35:24
不要相信你對字符串「知道」的內容。您可以通過源代碼查看字符串的實現。比如你的例子:
string s = "goodbye " + "cruel world!";
在java中會分配一個字符串。 Java扮演着一些非常可愛的技巧,並且很難超越智能 - 只有在需要時纔會進行優化!
然而,目前據我所知,使用這樣的:
String s="";
for(int i=0;i<1000;i++)
s+=" ";
仍然創造1000空間字符串往往是極其低效
在一個循環中追加是非常糟糕的,但除此之外,它是大概和StringBuilder一樣高效。
這是一個相當大的「否則」... StringBuilder將使用加倍,所以<10調整大小,而不是1000個副本(telescoping)。 – 2008-12-16 19:54:52
對,現在,避免在大循環中追加字符串,但不要強調它。即使如此,對於大多數代碼我都不會擔心,直到它開始影響性能。 – 2008-12-16 20:03:19
文字串是interned這意味着"hello "
確實不駐留在堆但在數據段[見註釋]的編程'的(並且因此沒有資格垃圾收集),同樣適用於"world"
,至於"hello world"
,如果編譯器足夠聰明的話,它也可能被攔截。
"goodbye cruel world"
將由於字符串文字連接被編譯器處理,所以被攔截。
編輯:我不知道有關數據段聲明,請參閱this question以獲取更多信息。
這裏要小心,因爲當編譯時已知字符串值時,編譯器可以做出一些非常不同的優化。如果你使用的字符串直到運行時才知道(從配置文件,數據庫或用戶輸入中提取),你會看到一些非常不同的IL。
如果你只是要做一個或兩個字符串連接,我不會擔心它。
但是,如果你有很多連接,或者你有一個循環,那麼你一定要採取預防措施。在Java世界中,這意味着您使用StringBuffer代替連接字符串。
如果它不只在一行中,則可以通過將第一個字符串變成一個StringBuffer,進行連接並返回結果字符串來完成兩個字符串的連接。
創建的StringBuffer自己看似矯枉過正,但是這就是將要發生anyway.-
通過一切手段不要過早優化,但不打折高性能串concatonations多麼嚴重的都可以。這不是對象創建,而是它引起的GC工作。
有一個實驗室(ASP.NET升級工程師)Tess Ferrnandez's博客,該博客顯示了一個(相當極端的,被授予的)how string concatonation can bring a server to its knees的示例。
公平:在這種情況下,字符串的兩部分在編譯時已知。如果有任何部分必須等到運行時纔會看到一些非常不同的IL。 – 2008-12-16 20:12:18
@Joel - 是的,但那是個問題。 – 2008-12-16 20:18:45