objective-c的set方法内存管理
基本数据类型如int不需要进行内存管理,但是凡是继承了NSObject的对象就需要进行内存管理。
引用计数器是oc内存管理一个很重要的部分。
alloc即开辟新内存时将计数器设置为1
retain:计数器+1
release:计数器-1
当计数器为0时,会自动销毁内存,系统自动调用dealloc方法。(ps: 这里可类比C++的析构函数,但又不尽相同。)
内存管理的有一条黄金法则:谁创建,谁释放。
关于set方法的内存管理策略,主要归纳为以下两点:
1. 重写set方法。
2. 重写dealloc方法。
很多时候,会出现一个类中含有另一个类的变量,或者说一个对象是另一个对象的属性。比如有一个Student类和一个Book类。Student类中含有Book变量。当Student的一个对象被释放的时候,对应的Book对象也会被释放。而如果还想在main函数中使用Book对象就需要重新创建了,这变得很麻烦。为了解决这个问题,需要在Student对象引用Book对象的时候将引用计数+1。而一般这种引用时出现在set方法中,所以在set方法中要先retain:
- (void)setBook:(Book *)book { _book = [book retain]; }
这样,从以下这一块可以看出,它是符合“谁创建,谁释放”这个法则的。
Student *stu = [[Student alloc] init]; Book *book = [[Book alloc] init];//book: 1 stu.book = book;//set方法时计数器+1,所以book: 2 [book release];//book: 1 ...
...
...
[stu release];
在[book release]释放后,因为其计数为1,stu对象的book对象仍能被使用:
[stu METHOD];
但是book对象使用后,又没有给它释放内存。所以要在Student.m中重写dealloc方法:(dealloc方法是继承于父类的NSObject中的)
- (void)dealloc { [_book release]; //[self.book release];与上面效果一样 [super dealloc];//这句一定要写在最后 }
这样在最后调用[stu release]的时候便可以将book计数器置为0,于是book对象得到释放。
但还有一个问题,当Book有多个对象时,在最后释放对象stu之前,对象stu中的变量_book得到的引用是最后使用的一个Book对象。所以在main函数中[stu release]时调用的重写的dealloc方法中[_book release]只会将最后使用的Book对象内存释放,而之前的Book对象的内存则不能被释放了。
void test(Student *stu) { Book *book = [[Book alloc] init];//book: 1 stu.book = book;//book: 2 [book release];//book: 1 Book *book2 = [[Book alloc] init];//book2: 1 stu.book = book2;//book2: 2 [book2 release];//book2: 1 } int main() { Student* stu = [[Student alloc] init];//stu: 1 test(stu); [stu release];// stu: 0, book2: 0, book: 1 }
因此,在每次使用Book对象给stu的变量_book赋值(即使用set方法时),要释放上一个_book引用的内存。
所以要修改set方法如下:
- (void)setBook:(Book *)book { [_book release];//释放上一个引用的内存,即使_book为nil,也不会报错 _book = [book retain]; }
另外,还要防止新赋的book和原来的_book相同的情况,比如以下重复赋相同值:
void test(Student *stu) { Book *book = [[Book alloc] init]; stu.book = book; [book release]; stu.book = book; }
如果出现这种情况,以上代码会导致野指针错误。
因此需要添加一个判断条件:
- (void)setBook:(Book *)book { if (_book != book) { [_book release]; _book = [book retain]; } }
这样内存就不会泄漏了。
PS:在学习过程中,编译器出现“EXC_BAD_ACCESS” 表示访问了已被释放的内存,即野指针错误。

浙公网安备 33010602011771号