摘要:不少語言對字符串的實現,都采用了限定不變性。字符串的不可變性有不少好處,但是如果程序員忘了這一點也會導致問題。所以字符串不可變就是存儲的代價。另一個場景是字符串可以用于哈希表的鍵,而鍵是不可以改變值的。
像是js,以及c#等一系列的語言,推出任何一個特征都要和c比一比,你知道的:)。
string的不可變性也是一樣,你看:
C的string是可以改變的。
你可以
char str[] = "Foo"; str[0] = ‘G"
str的內容確實被改變了。可以通過print來證明。打印內容,也打印指針。指針不變,內容變了。
2.js的不可改.如下的代碼,沒有任何效果,也可以log出來證明
var str = "foo";
str[0] = "g" ;
因為,語義上來說,這樣做意味著原位修改str的內存區(qū)內容
但是你可以
var str = "foo";
var = "bar"
因為原位置的內存沒有修改,是新分配的。只是打印不了指針,不好直接證明。要么就看代碼,那就啰嗦了。非常非常的啰嗦。
不少語言對字符串的實現,都采用了限定不變性。不能說這是不費解的:為何去創(chuàng)建一個新字符串,而不是去修改它呢?畢竟c就是這樣做的。
字符串的不可變性有不少好處,但是如果程序員忘了這一點也會導致問題。
如下的c#代碼會創(chuàng)建10000個字符串對象,但是除了最后一個,后面都是垃圾需要被回收的。
string s = string.Empty; for (int i = 0; i < 10000; i++) { s += "x"; }
通過cld profiler可以看到這張圖。
這樣的場景應該使用StringBuilder。而不是字符串連接。
StringBuilder sb = StringBuilder(); for( i = ; i < 10000; i++) { sb.Append(); } string x = sb.ToString();
針對js,也可以自己做一個StringBuilder
function StringBuilder() { this._array = []; this._index = 0; } StringBuilder.prototype.append = function (str) { this._array[this._index] = str; this._index++; } StringBuilder.prototype.toString = function () { return this._array.join(""); }
為何設計者決定實現不可變字符串呢?
這個和存儲優(yōu)化有關。字符串都存儲在俘虜池(intern pool)內,因為string都在intern pool內,所以,相同的字符串引用一致。這樣的存儲效果很好。
可是,如果允許修改string,那么a修改了,b也會跟著修改,d也是??墒?,語義上來說,我們認為他們是不同的變量,不應該聯動。所以字符串不可變就是intern pool存儲的代價。
string a = "xx"; string b = "xx"; string c = "x"; string d = String.Intern(c + c); Console.WriteLine((object)a == (object)b); Console.WriteLine((object)a == (object)d);
String的intern()方法就是擴充常量池的一個方法;當一個String實例str調用intern()方法時,c# 查找常量池中是否有相同Unicode的字符串常量,如果有,則返回其的引用,如果沒有,則在常量池中增加一個Unicode等于str的字符串并返回它的引用;
不變性,對多線程應用是有好處的。
另一個場景是字符串可以用于哈希表的鍵,而鍵是不可以改變值的。
string key = "abc"; Hashtable ht = new Hashtable(); ht.Add(key, 123); key = "xbc"; Console.WriteLine(key); // xbc Console.WriteLine(ht["abc"]); // 123
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/85554.html
摘要:整個這個雷區(qū)面板都是由的和組成的,最后由的方法對其進行不可變化處理剩下的主要邏輯部分就是掃雷了,傳入掃雷游戲對象一個不可變結構做為第一個參數,以及要掃的那個雷區(qū)塊對象,最后返回新的掃雷游戲實例。 不可變性(Immutability)是函數式編程的核心原則,在面向對象編程里也有大量應用。在這篇文章里,我會給大家秀一下到底什么是不可變性(Immutability)、她為什么還這么屌、以及在...
摘要:所有變量的類型在編譯時已知在程序運行之前,因此編譯器也可以推導出所有表達式的類型。像變量的類型一樣,這些聲明是重要的文檔,對代碼讀者很有用,并由編譯器進行靜態(tài)檢查。對象類型的值對象類型的值是由其類型標記的圓。 大綱 1.編程語言中的數據類型2.靜態(tài)與動態(tài)數據類型3.類型檢查4.易變性和不變性5.快照圖6.復雜的數據類型:數組和集合7.有用的不可變類型8.空引用9.總結 編程語言中的數據...
摘要:的不變性,如下圖所示,當你改變了的之后指向了一個新的對象原對象不做改變。但其引用的數組是可變的。所以的不可變性的關鍵并不是的作用。同時編寫者為了避免因為的不可變性導致占用大量空間,為此設計了字符串常量池 在貓眼的面試中被面試官問到為什么String的字符串是不變的。當時我的回答是因為String類是用final關鍵字修飾的,當被問到為什么用 final修飾就是不可變的時候我發(fā)現自己說的...
摘要:但是通過構造函數的并不是。通過構造函數創(chuàng)建的變量在機制上與其他對象一致,都是在上創(chuàng)建新的對象,然后把引用賦給變量。此外,的方法和等方法實現均是調用了構造函數創(chuàng)建了新的對象,所以他們返回的也都是存在于上的新對象。 String經常在一個語言中或多或少都有些特殊地位。在Java亦不例外。今天先來討論,String是不可變的。 String是引用類型,String變量儲存一個地址,地址指向內...
摘要:但在開始之前應該心中有數值的不可變性并不是說我們不能在程序編寫時不改變某個值。這些都是對值的不可變這個概念的誤解。程序的其他部分不會影響的賦值。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,是 HTML 最堅實的梁柱;分享,是 CSS 里最閃...
閱讀 2704·2021-11-22 15:24
閱讀 1441·2021-11-17 09:38
閱讀 2830·2021-10-09 09:57
閱讀 1267·2019-08-30 15:44
閱讀 2507·2019-08-30 14:00
閱讀 3617·2019-08-30 11:26
閱讀 2996·2019-08-29 16:28
閱讀 836·2019-08-29 13:56