NSString對象retainCount詳述

一概述

本文主要是關(guān)于基于64位系統(tǒng)下,NSString對象的retainCount分析。

二內(nèi)容

1.以下對象的retainCount為18446744073709551615也就是2的64次方減一,也就是ULONG_MAX

// @"123456789"是一個字符串常量,數(shù)據(jù)保存在數(shù)據(jù)區(qū),不在堆區(qū),是不可能
// 被釋放的,所以他的retainCount為ULONG_MAX,就算執(zhí)行release也不會有變化
// 這三個的內(nèi)存地址也是一樣的0x10bc89060,他們的class類型都為__NSCFConstantString
NSString *name = @"123456789";
NSString * name = [NSString stringWithString:@"123456789"];
NSString * name = [[NSString alloc] initWithString:@"123456789"];

// 下面的內(nèi)存地址于上面的不一樣,為0xa1ea1f72bb30ab19,class類型為NSTaggedPointerString
NSString * name = [NSString stringWithFormat:@"123456789"];

NSTaggedPointerString這個類表示這是字符串的一種指針Tagged Pointer,在蘋果推出了 采用64位架構(gòu)的A7雙核處理器 iphone 5s的時候,為了節(jié)省內(nèi)存和提高執(zhí)行效率,蘋果提出了Tagged Pointer的概念,這是為了從32位機器遷移到64位機器中后節(jié)省內(nèi)存。在蘋果的64位OC實現(xiàn)中,若對象指針的二進制第一位是1,則該指針為Tagged Pointer。

例如0xa1ea1f72bb30ab19其中a的2進制為1010,第一位1表示這是Tagged Pointer,010表示這是一個NSTaggedPointerString類;這個地址最后一位表示字符串的數(shù)目,這里是0101表示有9位字符串;其中真正用來存儲的位數(shù)只有中間的14位16進制。這個地址本身其實就存儲了字符串的值,可以說是存儲在&strS內(nèi)存中值,只是偽裝成了地址,它不需要存儲在數(shù)據(jù)區(qū),也不需要申請堆空間。
NSTaggedPointerString的存儲有三種編碼方式:ASCII碼,六位編碼,五位編碼。

六位編碼:
NSTaggedPointerString 采用六位二進制編碼,(14*4)/6=9.333…,可以看出最多存儲9位字符。字符數(shù)目8~9

五位編碼:
采用五位二進制編碼,(14*4)/5 = 11.2,可以看出這種編碼最多存儲11位字符。字符數(shù)目在10~11

1.以下對象的retainCount為1,class類型都為__NSCFString

// @"hello boy %@"和@"jack"這兩個是字符串常量,是無法修改的,所以由這兩個組成的是一個新的字符串就不能再他們基礎(chǔ)上修改得到,只能申請新的內(nèi)存,只能在堆里面申請,所以這時產(chǎn)生的NSString對象的retainCount為1
NSString *name = [[NSString alloc] initWithFormat:@"hello boy %@",@"jack"];
// 比較之前使用的stringWithFormat參數(shù)的對象的retainCount于之不一樣,因為現(xiàn)在的字符串超過了9個,所以無法使用NSTaggedPointerString來保存,只能申請新的內(nèi)存,所以這時產(chǎn)生的NSString對象的retainCount為1
NSString * name = [NSString stringWithFormat:@"1234567890"];

備注:因為retainCount返回的數(shù)據(jù)類型為NSUInteger,在64為系統(tǒng)中為8個字節(jié)無符號整數(shù),打印的時候需要使用%lu,如果使用%d,則本應(yīng)該輸出為2^64-1,會變成-1。

這是因為,數(shù)據(jù)保存的方式是補碼。正整數(shù)的原碼、反碼、補碼完全一樣,即符號位固定為0,數(shù)值位相同;負整數(shù)的符號位固定為1,由原碼變?yōu)檠a碼時,規(guī)則如下: 1原碼符號位1不變,整數(shù)的每一位二進制數(shù)位求反,得到反碼;2反碼符號位1不變,反碼數(shù)值位最低位加1,得到補碼。無符號2^64-1保存的二進制格式為64個1,如果按照有符號打印,按照補碼反推,1反碼符號位1不變,反碼數(shù)值位最低位減一1得到63個1加上最后一個0,2原碼符號位1不變,整數(shù)的每一位二進制數(shù)位求反得到開頭為1中間為62個0末尾為1的二進制數(shù),由于打印是%d,所以取32個低位數(shù),得到31個0和末尾一個1,剛好是-1.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容