Person * person=[[Person alloc]init];
Person* person仅是一个指针,它创建了一个指针指向了一个对象
[[Person alloc]init]这才是一个对象
Person * person是系统给他分配的空间,不需要我们来进行管理
NSLog(@"对象的地址:%p,指针的地址:%p",person,&person);
对象的地址:0x100202eb0,指针的地址:0x7fff5fbff8a8
0x100202eb0相当于房间号
0x7fff5fbff8a8这个是系统分配给指针的地址
当对象销毁,person指向的空间还是存在的,但是空间里放的已经不是原来的对象,如果对一个不存在的对象发送一个消息或调用一个方法程序就会崩溃
一个对象从空间里移出来,如果对给这个对象发送消息就会发生问题,就是僵尸对象
根本就不存在过渡释放,当一个对象不存在,再对这个对象发送这个对象不存在的消息(release消息)时这个对象就会崩溃
Person * person=[[Person alloc]init];
NSLog(@"对象的地址:%p,指针的地址:%p",person,&person);
[person release];
当对象释放以后,指针还是指向的,所以依然可以打印出和上面相同的地址
NSLog(@"对象的地址:%p,指针的地址:%p",person,&person);
走到这一步就会崩溃
NSLog(@"对象:%@",person);系统会默认拼接description方法
打印NSLog(@"对象:%@",person);相当于NSLog(@"对象:%@",[person description])
//只要没有retain ,copy,alloc的都是弱引用
//A进了办公室,开了里面的灯
Person * personA=[[Person alloc]init];
//C进了办公室,借用了里面的光,无强引用指向
Person * personC=personA;
//A和c都使用里面的光,都可以向对象发消息
[personA printf];
[personC printf];
//B进了办公室,同时B可以控制开关
Person * personB=[personA retain];
//A出办公室,灯没有关,release不具备关灯的方法,release并没有销毁对象,只是权限变了,指针的颜色由红色变成绿色,B依然有指针指向,在有强引用指向的情况下,A依然可以发送消息,但是一般我们遵守原则,一般不再对A发送消息,因为我不能确定A指向的空间其他对象B指向的红线什么时候消失。(只要有一条红线存在,都可以使用这个对象)。
[personA release];
//C虽然是弱引用,但是如果C发送一条release消息会把B对象变成弱引用,会造成这块地址没有强引用指向,A,B,C,任何对象再发送消息程序都会崩溃,所以我们要遵守规则,谁引用谁release
//[personC release];
//不应通过打印retaincount来判断应不应该release,而是应该通过retain,copy,alloc,new来判断,强引用的对象指针去release
[personA printf];
[personC printf];
[personB printf];
//B出办公室,灯没有关
// [personB release];
//dealloc是用来关灯的,也就是用来销毁对象的,不能手动调用,只能让系统去调用
只要有一个强引用指向,所有的指针都可以操作这个对象
autorelease
@autoreleasepool {
NSAutoreleasePool * pool=[[NSAutoreleasePool alloc]init];
[pool drain];
Pig * pig=[[Pig alloc]init];
Pig * pig00=[pig retain];
[pig release];
//autorelease没有权力将红线变绿线,出了离他最近的自动释放池才会将对象移出内存,假设自动释放池中有一个可变数组,当给pig发送autorelease,会把pig添加到数组中,当出自动释放池的时候,会把数组中的对象一一进行release,将强引用变成弱引用。不一定销毁。
[pig00 autorelease];
//autorelease有延迟,
}
return 0;
==============================================
//弱引用,如果自己是强引用自己进行release或者autorelease,尽量少用autorelease,因为autorelease有延迟,但有些情况必须使用。
Pig * pig=[Pig pig];
/*
+(Pig *)pig
{
Pig * pig=[[[Pig alloc]init]autorelease] ;
return pig;
}
*/
NSMutableArray * imageArr=[[NSMutableArray alloc]init];
for (int i=0; i<1000; i++) {
// NSString是一个弱引用,但是stringwithFormat是一个工厂方法,他里面实现的就是[NSString [alloc init]autorelease],然后return一个拼接的字符串;
NSString * str=[NSString stringWithFormat:@"%i",i];
[imageArr addObject:str];
[str release];//根据内存管理黄金法则,当str不再使用的时候,应该释放str,但是这个地方如果使用release,那么出自动释放池的时候autorelease会再出一次,就多发了一次,最好的解决办法就是在for循环中加入一个自动释放池,随时释放不再使用的str
}
}
用Copy还是用retain
@autoreleasepool {
//对于不可变的nsstring ,nsarray ,nsdictionary来说copy和retain没有区别,都是copy指针
NSString * str=@"hello";
NSString * str1=[str retain];
NSString * str2=[str copy];
NSString * str6=[str mutableCopy];
//对于不可变的字符串而言,如果使用mutableCopy就相当于复制一份新的地址出来
NSLog(@"%p %p %p",str,str1,str2);
[str1 release];
[str2 release];
NSMutableString * mutableStr=[[NSMutableString alloc]initWithFormat:@"hello"];
//只是复制了一个指针,一个对象改变时另一个对象也会变
NSString * str33=[mutableStr retain];
//copy复制了一份新的地址。
NSString * str44=[mutableStr copy];
NSLog(@"%p %p %p",mutableStr,str33,str44);
//因为父类指针可以指向子类对象,当一个不可变的字符串指向一个可变的字符串的时候,copy会复制一份对象的地址,但是如果用retain,相当于复制了一个指针,并没有复制地址,在这种情况下,如果一个字符串对象有两个指针指向,那么其中一个字符串指针改变对象的值时,由于另一个指针指向的是和它同一个对象,所以另一个指针指向的值也会发生改变,所以要用copy
Person * person=[[Person alloc]init];
//如果自定义对象用copy必须实现nscopying和nsmutablecopying协议方法,如果不实现这两个协议方法,调用copy时程序会报错。
Person * per=[person copy];
NSLog(@"%p %p",per,person);
}
Person需要遵守<NSMutableCopying,NSCopying>这两个协议,实现下面两个方法
- (id)copyWithZone:(NSZone *)zone
{
Person * person=[[Person alloc]init];
person.age=self.age;
return person;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
Person * person=[[Person alloc]init];
person.age=self.age;
return person;
}