内存管理高级

来源:互联网 发布:hmcl启动器 linux 编辑:程序博客网 时间:2024/06/06 03:42
现有Person类, 有属性如下:
@property(nonatomic,retain)Student*student;
@property(nonatomic,copy)NSString*name;
@property(nonatomic,retain)NSString*sex;

assign下的属性内部实现:
setter:
- (void)setName:(NSString*)name{
   
_name = name;
}
getter:
- (NSString*)name{
   
return _name;
}
对于基本数据类型的属性可以使用assign修饰, 基本数据类型生成在栈空间, 其内存有系统自动管理, 我们人工无法进行管理. 
对于类型属性若用assign修饰, 若在外部调用了setter, 并进行了一次释放, 则会肯能使_name指向被释放的内存空间, 有出现野指针的危险.

retain下的属性内部实现:
setter:
- (void)setName:(NSString*)name{
    if (_name != name) { —> 先判断, 传过来的对象和之前的成员变量是否相等
        [_namerelease]; —> 如果不同, _name 所指向的原来的内存空间引用计数-1,不一定是释放! 对于刚生成的对象, 其_name成员变量为空指针, 所以release时不会造成过度释放
        _name = [name retain]; —> 把新的内容赋给成员变量, 赋值前先让name引用计数+1, 防止野指针
    }
}
getter:
- (NSString*)name{
    return [[_name retain] autorelease]; —> return之前先retain一次,再autorelease一次,加减平衡. autorelease是因为,不知道外界什么时候用完,所以会等到出了释放池在release
}

发现:
Person*person1 = [[Personalloc]init];
Student *student1 = [[Studentalloc] init];
[student1retain];
NSLog(@"%lu", [student1retainCount]); —> 打印结果:2
person1.student= student1; —> 将 student1 赋给 person1 中的 student 成员变量, 赋值后二者指向同一块内存空间
NSLog(@"%lu", [student1retainCount]); —> 打印结果:3, 赋值期间, student1 所指向的内存空间引用计数 +1
[person1release];
NSLog(@"%lu", [student1retainCount]); —> 打印结果:3,
将person1 release后, student1所指向的内存空间引用计数并不-1, 重写dealloc方法原因即在于此! 关于dealloc, 见笔记: 8. 内存管理初级


copy下的属性内部实现:
setter:
- (void)setName:(NSString*)name{
    if (_name != name) {
        [_namerelease];
        _name = [name copy];
    }
}
getter: 同 retain下的属性内部实现

在便利构造器中考虑内存管理:
+ (id)personWithName:(NSString*)name
                sex:(NSString *)sex{
    Person *p = [[Personalloc]initWithName:nameage:age];
    return [p autorelease];
}
因此, 使用便利构造器创建的对象不需要考虑内存管理, 因为在便利构造器内部实现已考虑内存的自动释放

关于init初始化方法小记:
何时使用不带参数的初始化方法, 即, 直接alloc?
- 在不需要在初始化时对成员变量进行赋值时, 则不带参数, 但如果有数组或字典类型的成员变量, 则一定要初始化数组或字典, 否则添加对象的操作无效(参见homework5中addressbook类中的初始化方法).
0 0
原创粉丝点击