周末与一个老朋友吃饭聊天,因为他正在培训班学习iOS开发,就随便聊了几句,发现自己OC基础上的欠缺和一些知识点的混淆。特此整理如下。
1.空指针
没有存储任何内存地址的指针就称为空指针(NULL指针)
空指针就是没有被具体初始化之前,其值为0的指针
来两个例子
Person *p1 = nil;
Person *p2 = NULL;
下边会给出nil和NULL的区别
2.野指针
“野指针”不是空指针,野指针是指向了一块不可用的内存地址的指针,也就是说,野指针内是有保存一个内存地址的值,但是,指向的那个内存地址可能已经被释放,或者销毁。野指针会导致程序崩溃。
来个野指针的例子
Person *p1 = [[Person alloc]init];
[p1 setName:@"Rose"];
Person *p2 = p1;
[p1 release];
[p2 setName:@"Jack"];
上边的例子中,Person类中有方法setName:可以设置Person的姓名。
第3行代码中,将p1的内存地址赋值给p2,所以此时,p2和p1指向同一个内存空间。
第4行代码中,将p1的内存计数做一次release操作,根据内存管理机制,p1的内存地址被销毁。此时p2指针依然保存的是之前的地址的值。
第5行代码中,给p2所指向的对象发送了setName:的消息,但是此时对象已经被销毁了,内存已经不属于销毁对象了,所以代码会直接报错。
3.空指针和野指针
就上边的例子,我们来谈谈空指针和野指针的区别,首先我们看一个例子。
Person *p1 = [[Person alloc]init];
[p1 setName:@"Rose"];
Person *p2 = p1;
[p1 release];
p2 = nil;
[p2 setName:@"Jack"];
我们新加了第5行代码,将p2置为空指针,此时程序不会报错,这是因为p2是一个空指针,没有指向任何一个对象内存,因此,setName:消息是无法发送出去的,不会造成任何的影响,当然也不会报错。
所以,可以总结一下空指针和野指针的不同之处:
空指针中没有保存对象地址的值,野指针中一般保存了已销毁对象的内存地址值。
向空指针发送消息不会报错,但是给野指针发送消息会报错
野指针是非常危险的,非常危险的,非常危险的。。。重要的事情说三遍。借用别人的一句话:“设想,你家里有个物体,不知什么时候会突然出现,也不知道什么时候突然消失。会把你的东西乱挪乱动,还时不时打碎一个瓶子”
关于指针,有很多需要注意的操作事项,指针很强大,所以操作它需要很小心,操作不当的野指针,会造成不可预估的严重后果。
如果程序定义了一个指针,就必须要立即让它指向一个我们设定的空间或者把它设为NULL,如果没有这么做,那么这个指针里的内容是不可预知的,即不知道它 指向内存中的哪个空间(即野指针),它有可能指向的是一个空白的内存区域,可能指向的是已经受保护的区域,甚至可能指向系统的关键内存,如果是那样就糟 了,也许我们后面不小心对指针进行操作就有可能让系统出现紊乱,死机了。
所以我们必须设定一个空间让指针指向它,或者把指针设为NULL,这是怎么样的一 个原理呢?
如果是建立一个与指针相同类型的空间,实际上是在内存中的空白区域中开辟了这么一个受保护的内存空间,然后用指针来指向它,那么指针里的地址就 是这个受保护空间的地址了,而不是不可预知的啦,然后我们就可以通过指针对这个空间进行相应的操作了;如果我们把指针设为NULL,我们在头文件定义中的 #define NULL 0 可以知道,其实NULL就是表示0,那么我们让指针=NULL,实际上就是让指针=0,如此,指针里的地址(机器数)就被初始化为0了,而内存中地址为0 的内存空间……不用多说也能想象吧,这个地址是特定的,那么也就不是不可预知的在内存中乱指一气的野指针了。(摘自知乎用户郭无心)
4.nil、Nil、NULL、NSNULL的含义和区别
nil:OC中的对象的空指针
Nil:OC中类的空指针
NULL:C类型的空指针
NSNull:数值类的空对象
数值类:NSNumber,NSvalue,NSNull
此处说一下NSNull,在集合中不能nil值,因为NSArray和NSDictionary中nil有特殊的含义。但是有些时候,需要在集合中存放空值,比如个人信息中,只知道姓名,不知道电话号码,此时,有必要将电话号码设置为空,这时,就用到了NSNull。
NSNull中只有一个null方法 :[NSNull null]
[dic setObject:[NSNull null] forKey:@"phoneNumber"]; if(phoneNumber == [NSNull null]){
//...
}