Tagged Pointer 作用是什么?
為了改進從 32位CPU 遷移到 64位CPU 的內(nèi)存浪費和效率問題,在 64位CPU 環(huán)境下,引入了 Tagged Pointer 對象。有了這樣的機制,系統(tǒng)會對 NSString、NSNumber 和 NSDate等對象進行優(yōu)化。
原有的對象為什么會浪費內(nèi)存呢?
假設我們要存儲一個 NSNumber 對象,其值是一個整數(shù)。正常情況下,如果這個整數(shù)只是一個 NSInteger 的普通變量,那么它所占用的內(nèi)存是與 CPU 的位數(shù)有關,在 32 位 CPU 下占 4個字節(jié),在 64 位 CPU 下是占8個字節(jié)的。而指針類型的大小通常也是與 CPU 位數(shù)相關的,一個指針所占用的內(nèi)存在 32 位 CPU 下為 4 個字節(jié),在 64 位 CPU 下也是 8 個字節(jié)。
所以一個普通的 iOS 程序,如果沒有 Tagged Pointer 對象,從 32 位機器遷移到 64 位機器中后,雖然邏輯沒有任何變化,但這種 NSNumber、NSDate 一類的對象所占用的內(nèi)存會翻倍。

效率問題
從效率上來看,為了存儲和訪問一個 NSNumber 對象,我們需要在堆上為其分配內(nèi)存,另外還要維護它的引用計數(shù),管理它的生命周期。這些都給程序增加了額外的邏輯,造成了運行效率上的損失。
所以為了改進上面提到的內(nèi)存占用和效率問題,蘋果提出了 Tagged Pointer 對象,由于 NSNumber、NSDate 一類的變量本身的值需要占用的內(nèi)存大小常常不需要 8 個字節(jié),拿整數(shù)來說,4 個字節(jié)所能表示的有符號整數(shù)就可以達到 20 多億(2 ^ 31 = 2147483648,另外 1 位作為符號位),對于絕大多數(shù)情況都是可以處理的。
所以它將一個對象的指針拆分成兩部分,一部分直接保存數(shù)據(jù),另一部分作為特殊標記,表示這是一個特別的指針,不指向任何一個地址。
Tagged Pointer 特點:
-
Tagged Pointer專門用來存儲小的對象,例如NSNumber和NSDate -
Tagged Pointer指針的值不再是地址了,而是真正的值。所以,實際上它不再是一個對象了,它只是一個披著對象皮的普通變量而已。所以,它的內(nèi)存并不存儲在堆中。 - 在內(nèi)存讀取上有著 3 倍的效率,創(chuàng)建時比以前快 106 倍
還有一點,注意??
所有對象都有 isa 指針,而Tagged Pointer其實是沒有的,因為它不是真正的對象。因為不是真正的對象,所以如果你直接訪問Tagged Pointer的isa成員的話,編譯時將會有如下警告。應該換成相應的方法調(diào)用,如 isKindOfClass 和 object_getClass。只要避免在代碼中直接訪問對象的 isa 變量,即可避免這個問題。