NSString在不同的初始化方式導(dǎo)致的神奇現(xiàn)象

本文主要是實驗了兩個不同的NSString初始化方法導(dǎo)致的奇怪現(xiàn)象昧狮,因為能力有限,只進行了一番簡單的解釋终息,拋磚引玉。最后附上了一些猜想贞让,供君參考周崭。

1.當NSString長度小于10時,不再遵循引用計數(shù)規(guī)則

如果不能理解【引用計數(shù)規(guī)則】可以參考下另一篇文章iOS中copy,strong,retain,weak和assign的區(qū)別震桶。
實驗代碼如下

NSString *stringLess10 = [[NSString alloc] initWithUTF8String:"123456789"];
NSString *string1Less10 = [[NSString alloc] initWithUTF8String:"123456789"];
NSLog(@"stringLess10值地址%p,引用計數(shù)%@",stringLess10,[stringLess10 valueForKey:@"retainCount"]);
NSLog(@"string1Less10值地址%p,引用計數(shù)%@",string1Less10,[string1Less10 valueForKey:@"retainCount"]);

NSString *stringMore10 = [[NSString alloc] initWithUTF8String:"12345678910"];
NSString *string1More10 = [[NSString alloc] initWithUTF8String:"12345678910"];
NSLog(@"stringMore10值地址%p,引用計數(shù)%@",stringMore10,[stringMore10 valueForKey:@"retainCount"]);
NSLog(@"string1More10值地址%p,引用計數(shù)%@",string1More10,[string1More10 valueForKey:@"retainCount"]);

輸出結(jié)果:

stringLess10值地址0xa1ea1f72bb30ab19,引用計數(shù)18446744073709551615
string1Less10值地址0xa1ea1f72bb30ab19,引用計數(shù)18446744073709551615
stringMore10值地址0x6080000306e0,引用計數(shù)1
string1More10值地址0x6080000306a0,引用計數(shù)1

現(xiàn)象:stringLess10和string1Less10值地址相同且引用計數(shù)異常休傍,但在字符串長度大于10的stringMore10和string1More10上這個現(xiàn)象就不存在了
解釋:當NSString長度小于10時不再遵循引用計數(shù)規(guī)則,Tagged Pointer技術(shù)對其進行了優(yōu)化蹲姐∧ト。基本意思就是默認會將一些長度小于10的字符串直接保存在指針上面,下次創(chuàng)建相同值的時候直接用同一份拷貝柴墩,這樣既減少了一次指針到值的訪問忙厌,又減少了一份內(nèi)存的占用。
深入資料:http://www.cocoachina.com/ios/20150918/13449.html

2.NSString直接字符串賦值的異常

實驗代碼:

NSString *stringWithOutInit = @"1234567891011";
NSLog(@"stringWithOutInit,值地址%p,引用計數(shù)%@",stringWithOutInit,[stringWithOutInit valueForKey:@"retainCount"]);

輸出結(jié)果:

stringWithOutInit,值地址0x1081f7180,引用計數(shù)18446744073709551615

現(xiàn)象:值地址相當靠前江咳,如一般是0xa1ea1f72bb30ab19逢净,而他是0x1081f7180。另外引用計數(shù)非常大歼指。
解釋:直接字符串賦值和init系列初始化方法有所不同爹土。前者創(chuàng)建的是一個常量,不遵循引用計數(shù)踩身。且在App結(jié)束前不會被釋放掉胀茵。引用計數(shù)在這個不能被釋放的內(nèi)存塊上默認返回是一個很大的值
我們通過weak類型來接收這個值,并把stringWithOutInit設(shè)置nil挟阻,驗證原來的內(nèi)存塊是否會釋放
實驗代碼

__weak NSString *weakStr = stringWithOutInit;
stringWithOutInit = nil;
NSLog(@"weakStr指針地址%p,值地址%p,引用計數(shù)%@,值為%@", &weakStr,weakStr,[weakStr valueForKey:@"retainCount"],weakStr);

輸出:

weakStr值地址0x1081f7180,值為1234567891011

發(fā)現(xiàn)值地址就是之前stringWithOutInit的值地址琼娘,且值依舊存在。
現(xiàn)象:雖然只有弱指針指向這個內(nèi)存塊附鸽,但依舊有值存在脱拼,未被釋放。
解釋:因為常量的引用計數(shù)無限大坷备,自然值就不會被釋放

3.附加猜測NSString內(nèi)存中的存儲方式

我們知道NSMutableString對象的指針地址和值地址分別在棧和堆上熄浓,那么我們可以通過他的指針地址和棧地址來猜測nsstring不同方式初始化的時候指針和值地址在堆還是在棧上
試驗代碼:

NSMutableString *mstr = [[NSMutableString alloc] initWithFormat:@"%@",@"asdfasdfffffff"];
    NSLog(@"mstr指針地址:%p 值地址%p,引用計數(shù)%@",&mstr,mstr,[mstr valueForKey:@"retainCount"]);
    NSLog(@"stringLess10指針地址:%p 值地址%p,引用計數(shù)%@",&stringLess10,stringLess10,[stringLess10 valueForKey:@"retainCount"]);
    NSLog(@"stringMore10指針地址:%p 值地址%p,引用計數(shù)%@",&stringMore10,stringMore10,[stringMore10 valueForKey:@"retainCount"]);
    NSLog(@"stringWithOutInit指針地址:%p 值地址%p,引用計數(shù)%@",&stringWithOutInit,stringWithOutInit,[stringWithOutInit valueForKey:@"retainCount"]);

輸出結(jié)果:

mstr指針地址:0x7fff51dbbaa8 值地址0x60800006bc00,引用計數(shù)1
stringLess10指針地址:0x7fff51dbbaf8 值地址0xa1ea1f72bb30ab19,引用計數(shù)18446744073709551615
stringMore10指針地址:0x7fff51dbbae8 值地址0x600000024a80,引用計數(shù)1
stringWithOutInit指針地址:0x7fff51dbbad0 值地址0x0,引用計數(shù)(null)

現(xiàn)象和結(jié)論:
指針地址都是12位且值都相近,所以NSString不管初始化如何指針依舊保存在棧上面省撑。
stringMore10和mstr值地址相近玉组,所以init初始化方式在長度大于10的時候默認值存放在堆上谎柄。
stringLess值地址10長度為16位,完全不在堆上惯雳。
stringWithOutInit值地址沒有朝巫,說明他也不在堆上面,且和stringLess值存儲方式不一樣石景。

交流qq:578172874
錯誤之處還希望能幫忙提出來,一起學(xué)習(xí)劈猿,O(∩_∩)O謝謝了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市潮孽,隨后出現(xiàn)的幾起案子揪荣,更是在濱河造成了極大的恐慌,老刑警劉巖往史,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仗颈,死亡現(xiàn)場離奇詭異,居然都是意外死亡椎例,警方通過查閱死者的電腦和手機挨决,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來订歪,“玉大人脖祈,你說我怎么就攤上這事∷⒔” “怎么了盖高?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眼虱。 經(jīng)常有香客問我喻奥,道長,這世上最難降的妖魔是什么捏悬? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任撞蚕,我火速辦了婚禮,結(jié)果婚禮上邮破,老公的妹妹穿的比我還像新娘诈豌。我一直安慰自己仆救,他們只是感情好抒和,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彤蔽,像睡著了一般摧莽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顿痪,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天镊辕,我揣著相機與錄音油够,去河邊找鬼。 笑死征懈,一個胖子當著我的面吹牛石咬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卖哎,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼鬼悠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了亏娜?” 一聲冷哼從身側(cè)響起焕窝,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎维贺,沒想到半個月后它掂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡溯泣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年虐秋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片发乔。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡熟妓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栏尚,到底是詐尸還是另有隱情起愈,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布译仗,位于F島的核電站抬虽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纵菌。R本人自食惡果不足惜阐污,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咱圆。 院中可真熱鬧笛辟,春花似錦、人聲如沸序苏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忱详。三九已至围来,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背监透。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工桶错, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胀蛮。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓院刁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親粪狼。 傳聞我的和親對象是個殘疾皇子黎比,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,284評論 0 6
  • 多線程鸳玩、特別是NSOperation 和 GCD 的內(nèi)部原理阅虫。運行時機制的原理和運用場景。SDWebImage的原...
    LZM輪回閱讀 2,004評論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,962評論 0 7
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,712評論 0 4
  • 1.寫一個NSString類的實現(xiàn) +(id)initWithCString:(c*****t char *)nu...
    韓七夏閱讀 3,747評論 2 37