内存管理

本文详细阐述了Objective-C中的内存管理机制,包括垃圾回收、手动管理引用计数(MRC)和自动管理引用计数(ARC),并展示了如何正确使用retain、release和autorelease方法,以及如何在内存管理中遵循原则。同时,介绍了不可变和可变对象的转换,以及如何在自定义类中实现copy功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// 管理内存有三种方法
// 一:垃圾回收,java常见的管理内存的方法,系统来检测对象是否被使用,是否被释放
// 二:MRC手动管理引用计数,iOS管理内存的方式,程序员通过手动方式来管理对象是否被释放
// 三:ARC自动管理引用计数,基于MRC,系统自动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯

1.
对象被创建出来之后它的引用计数retainCount就变成1
Boy *boy=[[Boy alloc] init];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:19:04.268 OC08,09_内存管理[4084:303] 1
// retain:对对象的引用计数+1
[boy retain];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:20:01.061 OC08,09_内存管理[4095:303] 2
[boy retain];
[boy retain];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:20:01.061 OC08,09_内存管理[4095:303] 4

// release:对对象的引用计数-1
[boy release];
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:21:12.346 OC08,09_内存管理[4110:303] 3
[boy release];
[boy release];
[boy release];
在Boy.m中
-(void)dealloc{
NSLog(@”对象被释放掉了”);
// 把成员变量里的+1的操作全部减去
[_name release];
[_girls release];
[_hobby release];

[super dealloc];

}
2015-07-27 19:21:12.347 OC08,09_内存管理[4110:303]对象被释放掉了
// 当对象的引用计数1->0的时候,会自动的调用dealloc方法,dealloc才是对应对象释放的方法
// 当对象调用release的时候,它的引用计数是1,这个对象就不在对它的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象的引用计数还是1
// 如果多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题
2.NSString 的对象在全局静态区,它的引用计数是-1,代表正整数的最大值,其他的对象都在堆区
NSArray *arr=@[@”1”,@”2”,@”3”,@”4”];
NSLog(@”%ld”,arr.retainCount);
2015-07-27 19:23:55.669 OC08,09_内存管理[4150:303] 1
NSString *str=@”111111”;
NSLog(@”%ld”,str.retainCount);
2015-07-27 19:23:55.679 OC08,09_内存管理[4150:303] -1
NSMutableString *str2=[NSMutableStringstringWithString:@”1111”];
NSLog(@”%ld”,str2.retainCount);
2015-07-27 19:23:55.679 OC08,09_内存管理[4150:303] 1
NSMutableArray *arr2=[NSMutableArray arrayWithArray:@[@”1”,@”2”,@”3”,@”4”]];
NSLog(@”%ld”,arr2.retainCount);
2015-07-27 19:23:55.680 OC08,09_内存管理[4150:303] 1
NSDictionary *dic=@{@”1”:@”2”,@”3”:@”4”};
NSLog(@”%ld”,dic.retainCount);
2015-07-27 19:23:55.680 OC08,09_内存管理[4150:303] 1
3.release马上回把对象的引用计数-1,但是autorelease会延迟对对象的计数-1
自动释放池:只要对象用autorelease释放会把对象放入到系统的自动释放池中,等出了池子范围,对象引用计数自动-1,这个相当于java的垃圾回收,对象释放由系统来管理
Boy *boy=[[Boy alloc] init];
[boy retain];
[boy retain];
[boy release];
@autoreleasepool {
[boy autorelease];
NSLog(@”%ld”,boy.retainCount);
}
NSLog(@”%ld”,boy.retainCount);
2015-07-27 19:28:40.550 OC08,09_内存管理[4209:303] 2
2015-07-27 19:28:40.550 OC08,09_内存管理[4209:303] 1
4.内存管理的原则:加多少,对应减多少,加减做到平衡
对象的所有权:拥有所有权的对象可以对他进行release
对象如果是我们进行alloc或者retain之后我们就获取了对象的所有权,就可以对对象进行release操作
便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不需要对内存进行管理
id是泛型指针,可以用在任何的方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
5.不可变->可变
(1) NSMutableArray *arr1=[NSMutableArrayarrayWithArray:arr];
(2) NSMutableArray *arr2=[arrmutableCopy];
[arr2 addObject:@”5”];
NSLog(@”%@”,arr2);
2015-07-27 19:31:49.456 OC08,09_内存管理[4276:303] (
1,
2,
3,
4,
5
)
6.系统的类要是实现copy拷贝功能,必须先签订拷贝NSCopying的协议,然后实现对应的方法
不可变的数组字典可以通过mutableCopy转换成可变的数组字典
mutableCopy出来的对象是可变的,copy是不可变的
如果自己的类想要实现copy的功能,就必须先签订NSCopying,然后实现对应的协议方法,initWithZone,之后就可以使用copy功能
copy也可以改变引用计数,但是它改变的是新对象的引用计数,而原先的对象计数不变
当对象放入到容器Array或者字典中,对象会被容器进行一次持有,就是retain一次,它的引用计数会+1,主要是为了防止空指针的问题
等对象从容器中移除掉之后,相应得会-1
-(void)setName:(NSString *)name{
if (_name!=name) {
[_name release];
_name=[name retain];
}
// [name retain];
// [_name release];
// _name=name;
}
7.创建一个类Person
Person.h

import

import “Person.h”

@implementation Person

-(id)initWithName:(NSString *)name
age:(NSInteger)age{
self=[superinit];
if (self) {
self.name=name;
self.age=age;
// _age=age;
// 对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免因为忘了,造成问题
self.arr=[NSMutableArrayarray];
}
return self;

}

+(Person )personWithName:(NSString )name
age:(NSInteger)age{
Person *person=[[Personalloc] initWithName:nameage:age];
return [person autorelease];

}

-(void)dealloc{
[_arr release];
[_name release];
[super dealloc];
}

@end

main.m
Person *per=[[Personalloc] initWithName:@”张三”age:20];
[per.arr addObject:@”1”];
NSLog(@”%@”,per.arr);
2015-07-27 19:31:49.457 OC08,09_内存管理[4276:303] (
1
)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值