一、iOS 程序内存布局
1.重点掌握下图,我们可以理解很多东西
内存布局图
2. 通过下面代码,强化我们的理解
void func(){ //代码区
printf("func");
}
const int a = 10; //常量区
int c = 20; //全局数据区
int main() {
NSString *b = @"我是chinese"; // 字符串在常量区; &b在栈区
static int d = 30; //全局数据区
NSObject *e = [[NSObject alloc] init];//对象在堆区; &e在栈区
NSLog(@"%p",func);
NSLog(@"\na=%p\nb=%p\nc=%p\nd=%p\ne=%p\n&e=%p\n", &a, b, &c, &d, e, &e);
}
二、Tagged Pointer
1. Tagged Pointer基本介绍
- 从
64bit
开始,iOS 引入了 Tagged Pointer
技术,用于优化 NSNumber、NSDate、NSString 等小对象的存储
- 在没有使用
Tagged Pointer
之前,NSNumber 等对象需要动态分配内存、维护引用计数器等,NSNumber 指针
存储的是堆中 NSNumber 对象的地址值
- 使用
Tagged Pointer
之后,NSNumber 指针
里面存储的数据变成了:Tag+Data
,也就是将数据直接存储在了指针中
- 当指针不够存储数据时,才会使用动态分配内存的方式来存储数据
-
objc_msgSend
能识别 Tagged Pointer
,比如 NSNumber
的 intValue
方法,直接
从指针提取数据,节省
了以前的调用开销
2. 如何判断一个指针是否为 Tagged Pointer
- iOS 平台,指针最高有效位是 1(第 64bit)
- Mac 平台,指针最低有效位是 1
3. Tagged Pointer 从代码中窥探它们
- (void)viewDidLoad {
[super viewDidLoad];
NSNumber *a = @1;
NSNumber *b = @2;
NSNumber *c = @(2020202020202002022);
NSLog(@"%p,%p,%p",a,b,c);
NSString *aa = [NSString stringWithFormat:@"123abc"];
NSString *aa2 = [NSString stringWithFormat:@"123abc"]; // 发现 aa2 的地址值和 aa 是相同的
NSString *bb = [NSString stringWithFormat:@"abcd"];
NSString *cc = [NSString stringWithFormat:@"abcabcabcabcabcabcabcabc"];
NSLog(@"%p,%p,%p,%p",aa,aa2,bb,cc);
NSLog(@"%@,%@,%@", [aa class], [bb class], [cc class]);
}
Demo[5902:460945] 0xb8736ae365a09e56,0xb8736ae365a09e66,0x600000b6cfa0
Demo[5902:460945] __NSCFNumber,__NSCFNumber,__NSCFNumber
Demo[5902:460945] 0xa8755cc57693bd52,0xa8755cc57693bd52,0xa8736ae52396b850,0x60000059ef40
Demo[5902:460945] NSTaggedPointerString,NSTaggedPointerString,__NSCFString
- 我们可以从代码中看出:
- 当字符串够短,能够用指针存下时,OC 就不会创建
堆对象
,而是使用 Tagged Pointer
技术来表示
- 两个内容相同的
Tagged Pointer
,他们的指针也是一摸一样的。
-
Tagged Pointer
的地址最高位都是 0b1
网友评论