黑马程序员——OC---MRC里的循环retain问题

本文详细解析了对象retain与dealloc机制在编程中的应用,通过一个实例代码演示了对象引用计数的作用以及如何避免内存泄露的问题。文章指出,通过在main函数中额外调用一次release或使用assign替代retain,可以确保对象的正常销毁过程。

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

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------



循环retain问题即A对象retainB对象,B对象同时也retainA对象。

Book

#import <Foundation/Foundation.h>
@class Person;
@interface Book : NSObject
@property(nonatomic,retain)Person *author;
@end

#import "Book.h"

@implementation Book
- (void)dealloc
{
    [_author release];
    NSLog(@"Book----->dealloc");
    [super dealloc];
}
@end

Person

#import <Foundation/Foundation.h>
@class Book;
@interface Person : NSObject
@property(nonatomic,retain)Book *bigBook;
@end

#import "Person.h"

@implementation Person
- (void)dealloc
{
    [_bigBook release];
    NSLog(@"Person----->dealloc");
    [super dealloc];
}
@end

main

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [Person new];
        Book *b = [Book new];
        
        p.bigBook = b;
        b.author =p;
        
        [p release];
        [b release];
    }
    return 0;
}

上面代码看似很正确,p->new然后p->release,b->new然后b->release,并且都重写了dealloc方法,也再释放自己的同时释放了自己的实例对象。

但程序运行毫无结果,即无法打印出Book----->dealloc,也无法打印出Person----->dealloc。

在main代码调用release之前加行代码

<span style="font-size:14px;">NSLog(@"%ld\t%ld",p.retainCount,b.retainCount);</span>
打印发现p和b的计数器都是2,这是因为p和b的set方法都会将传入的对象retain一次,导致p和b的计数器都变为2,而在main中只分别调用了一次release,这样p和b的计数器都是1,所以他都没有调用dealloc方法。


解决方法一是再在main函数里用 p或者b调用一次release,不过这种方法可能会由于顺序或者其他原因导致报错或警告,并不安全。

另一种解决方法是将Person类的retain换成assign,注意换成assign 的那个类(Person类)的dealloc方法就不必再进行release了,因为assign并不会在set方法中对传入的对象进行retain,所以被传入对象的计数器不会+1,这样在程序进行到

[p release];
[b release];
的时候p的计数器为2,b的计数器为1,[p release]之后计数器变为1,[b release]之后b的计数器为0,b摧毁,b调用dealloc方法,dealloc方法会进行 [p release]操作,p的计数器为0,p摧毁,p调用dealloc方法。程序到此正常结束。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值