在OC单例中,全局变量personKey的地址为何发生变化?
嗨,这个问题其实是C/Objective-C里static关键字作用域的经典坑,我来给你拆解清楚:
你在头文件里写了static const void* personKey = &personKey;,这里的static会导致每个引入该头文件的编译单元(简单说就是每个.m文件)都会生成一个完全独立的personKey实例。
举个例子:
- 当
Person.m引入Person.h时,编译器会在Person.m的编译范围内生成一个personKey变量; - 如果有另一个类
Student.m也引入了Person.h,编译器同样会在Student.m的编译范围内生成另一个完全不同的personKey变量。
这两个变量只是名字相同,但内存地址完全不一样——你在sharedPerson里打印的是Person.m里的那个副本的地址,要是在其他类里打印这个变量,看到的就是另一个副本的地址,自然会觉得“地址变了”。
解决办法:让变量真正全局唯一
要让personKey成为整个项目中唯一的全局变量,需要把声明和定义分开:
- 在
Person.h里用extern声明变量(告诉编译器这个变量在其他地方定义):
#import <Foundation/Foundation.h> extern const void* personKey; @interface Person : NSObject +(instancetype)sharedPerson; @end
- 在
Person.m里定义这个变量(去掉static,让它成为全局可见的):
#import "Person.h" const void* personKey = &personKey; static Person *_person; + (instancetype)sharedPerson { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _person = [[self alloc] init]; printf("personkey111 = %p\n",personKey); }); return _person; } @end
这样不管哪个类引入Person.h,访问的都是Person.m里定义的同一个personKey变量,地址自然就不会变了。
内容的提问来源于stack exchange,提问作者nenseso
相关产品推荐
相关产品推荐

