蘋果對於Tagged Pointer特色的介紹:c++
iPhone5s 採用64位處理器。
對於64位程序,咱們的數據類型的長度是跟CPU的長度有關的。objective-c
這樣就致使了 一些對象佔用的內存會翻倍。測試
同時 維護程序中的對象須要 分配內存,維護引用計數,管理生命週期,使用對象給程序的運行增長了負擔。ui
爲了改進上面提到的內存佔用和效率問題,蘋果提出了Tagged Pointer對象。因爲NSNumber、NSDate一類的變量自己的值須要佔用的內存大小經常不須要8個字節,拿整數來講,4個字節所能表示的有符號整數就能夠達到20多億(注:2^31=2147483648,另外1位做爲符號位),對於絕大多數狀況都是能夠處理的。this
咱們能夠將一個對象的指針拆成兩部分,一部分直接保存數據,另外一部分做爲特殊標記,表示這是一個特別的指針,不指向任何一個地址。因此,引入了Tagged Pointer對象以後,64位CPU下NSNumber的內存圖變成了如下這樣:
Tagged Pointerspa
#importint main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSNumber *number1 = @1; NSNumber *number2 = @2; NSNumber *number3 = @3; NSNumber *numberFFFF = @(0xFFFF); NSNumber *numberLager = @(MAXFLOAT); NSLog(@"number1 pointer is %p", number1); NSLog(@"number2 pointer is %p", number2); NSLog(@"number3 pointer is %p", number3); NSLog(@"numberLager pointer is %p", numberLager); /* 2017-03-10 12:07:50.731726 TaggedPoint[1690:50438] number1 pointer is 0x127 2017-03-10 12:07:50.731992 TaggedPoint[1690:50438] number2 pointer is 0x227 2017-03-10 12:07:50.732011 TaggedPoint[1690:50438] number3 pointer is 0x327 2017-03-10 12:07:50.732043 TaggedPoint[1690:50438] numberLager pointer is 0x1002006a0 */ } return 0; } 複製代碼
以 0x127 爲例 去掉 tag27(假設27爲標記) 0x1 就是number 的值。
0x227
0x327
都有這種規律指針
numberLager 存儲的值爲MAXFloat 顯然超過了tagged pointer 能夠存儲的範圍。
因此打印的地址是單純的指針地址,指向存儲numberLager的內存地址。code
由於tagged pointer 不是一個真正的對象,若是使用isa指針在編譯時會報錯。
如圖:cdn
因爲object_getClass()沒有對應的實現,只能從其餘地方窺探一二
objc-weak.mm對象
weak_read_no_lock(weak_table_t *weak_table, id *referrer_id)
{
objc_object **referrer = (objc_object **)referrer_id;
objc_object *referent = *referrer;
if (referent->isTaggedPointer()) return (id)referent;
//...
}複製代碼
inline bool
objc_object::isTaggedPointer()
{
#if SUPPORT_TAGGED_POINTERS
return ((uintptr_t)this & TAG_MASK);
#else
return false;
#endif
}複製代碼
這裏取對象的值作了一些判斷若是是tagged pointer , 對象的值就是指針若是非tagged pointer , 對象的值是指針指向的內存區域中的值