c语言中
每初始化一次对象:计数器为1
释放对象时:计数器-1
被引用的指针计数器为0时
被引用该指针的内存自动释放,引用指针成为野指针
除了c语言的基本数据类型外
oc中得类都加入了对象引用计数 retainCount
1.手动管理引用计数
2.自动管理引用计数 autorelease
NSString特殊
调用对象的retian copy mutaleCopy new alloc会影响该对象的引用计数为1
调用对象的release autorelease会使该对象的引用计数-1
NSString *str1 = [[NSString alloc] init];
//不遵循黄金法则即使初始化 str1.retainCount 为-1 但为了统一黄金法则 依然要release
NSLog(@"%ld",str1.retainCount);
ARC中
NSMutableString * str = [[NSMutableStringalloc]init];
//只有oc的对象才有retainCount c中没有
NSLog(@"%ld",str.retainCount);//1
[str retain];
NSLog(@"%ld",str.retainCount);//2
[str release];
NSLog(@"%ld",str.retainCount);//1
//不写下面内存泄露
[str release];
/*
内存管理:谁申请 谁释放
一对一原则:引用计数+1 或-1 要平衡
*/
Person *p = [[Personalloc]init];
NSLog(@"count %ld",p.retainCount);
[pretain];
NSLog(@"count %ld",p.retainCount);
[prelease];
[prelease];
NSMutableString *str2 = [[NSMutableStringalloc]initWithString:@"wahaha"];
p.Str = str2;
NSLog(@"%ld",str2.retainCount);//2
p.Str = str2;
NSLog(@"%ld",str2.retainCount);//2
[strrelease];
NSLog(@"Str is %@",p.Str);
//如果是有两个对它进行赋值,如果set方法单纯的用self.Str = Str会崩掉,如果使用self.Str = [Str retain],那么对它进行两次对象的赋值的话第一次赋值的self.Str空间没有被释放,而self.Str现在指向了另一个空间,所以原来的self.Str的retain没有被释放所以set方法应该向Person类里面写的那样
NSMutableString *str3 = [[NSMutableStringalloc]initWithString:@"aaa"];
p.Str = str2;
NSLog(@"%ld",str2.retainCount);//2
p.Str = str3;
NSLog(@"%ld",str3.retainCount);//2,str2.retainCount变成1
Person.h文件
{
NSMutableString *_Str;
}
@property (nonatomic ,retain)NSMutableString *Str;
/*
不要手动调用对象的dealloc方法
当该对象的引用计数为0时系统自动调用
对象的成员变量释放都写在dealloc中
*/
-(void) dealloc
{
//不写内存泄露
[self.Strrelease];
//只能在非ARC中书写
[superdealloc ];
}
//点语法扩展
-(void)setStr:(NSMutableString *)Str
{
//self .Str = Str; 错误,当释放了str,在调用self.str会崩掉
//self.Str = [Str retain];强引用错误,内存泄露
if (self.Str != Str) {
[self.Strrelease];//如果没有实例化,self.Str为空指针,对空指针进行释放是合法的,释放的后的内存地址不变
self.str = [Strretain];//对Str空间进行强引用
}
}
//此方法其实保证self.Str被第二个其他字符串引用时,原来的字符串的retain变回self.Str没有被引用的时候,就像人从a房间走到b房间,a房间的人数要减去1,再把b房间的人数增加1
-(NSMutableString *)Str
{
return self.Str;
}