您的位置:首页 > 其它

2015.9.17 第十一堂 内存管理(下) [注:时间为学习时间,非原时间]

2015-09-16 20:45 274 查看
一、延迟释放 autorelease



上图,为一个错误写法:

如图写,release释放后被销毁,无法返回结果

如果返过来写:先返回再释放 ,直接return掉了不会执行return后的语句。

如果不释放掉,内存又会泄露。

出了这个代码块,其他代码块对path没有拥有权,也不可以释放。

所以引入新概念:延迟释放autorelease

//从一个方法返回某个对象,这个对象不能立刻释放,就可以使用autorelease
当某一个对象被autorelease修饰的时候,这个对象将会被扔到自动释放池里面,系统每隔一段时间会到自动释放池里面去判断某个对象的生命周期结束没有。如果结束那么会立刻销毁掉这个对象,如果没有结束会一直存在。
 release: 
    优点:可以立刻释放某个对象,对内存的消耗不大
    缺点:开发者必须非常清晰什么时候去释放某个对象,不利于管理
 autorelease:
    优点:操作方便 出错概率小 alloc/new/copy/mutablecopy?匹配autorelease
    缺点:不能立刻将内存空间释放出来,对内存的消耗比较大,运行效率不高

二 dealloc
没听懂!!!!!!

         释放对某个对象的拥有权用release或者autorelease
         当释放某个对象本身之前,需要先释放这个对象拥有的一些资源,这个释放过程就放在dealloc方法里面
         dealloc是NSObjecy里提供的方法,不能主动调用,由系统调用
先待定!!!!!!



//dealloc释放掉对象本身拥有的对象的拥有权
//即释放掉对象本身拥有的对象
//当这个对象被释放的时候,系统会首先自动调用这个对象的dealloc方法

#ifndef dealloc_Header_h
#define dealloc_Header_h
//建立一个header 命名为Constants

#define release_nil(x) ([x release],(x)=nil)

#endif
创建宏定义 #define release_nil(x) ([x release],(x)=nil)
-(void)dealloc{
//    [_name release]; _name=nil;
//    [_studentsArray release],_studentsArray=nil;
release_nil(_name);
release_nil(_studentsArray);

[_ddd release];
[super dealloc];
}


用release_nil宏不会造成过度释放:因为释放完后把指针置为nil(即指向0x0这块特殊的内存区)。若不小心再度释放,因为是对nil(0x0)进行释放,这是安全的,所以不会导致程序的崩溃。

三 property内存管理

在.h文件中 声明count属性和一个reSetNumber方法

//
//  Counter.h
//  property内存管理
//
//  Created by tusm on 15-9-17.
//  Copyright (c) 2015年 tusm. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Counter : NSObject

@property (nonatomic,strong)NSNumber *count;

-(void)reSetNumber:(NSNumber *)number;

@end


//
//  Counter.m
//  property内存管理
//
//  Created by tusm on 15-9-17.
//  Copyright (c) 2015年 tusm. All rights reserved.
//

#import "Counter.h"

@implementation Counter

-(void)dealloc{
[_count release],_count=nil;
[super dealloc];
}

//setter方法如下:
//注意:在重写setter方法的时候不能用点语法,这样会导致死循环
-(void)setCount:(NSNumber *)count{
if (self.count != count) {//getter方法可以哈
//先释放旧的
[_count release];

//保存新的
_count=[count retain];//外面传给我的count 在这里我要对她声明拥有权
}
}

//property的setter方法实现了内存管理相关内容
//所以在对属性变量赋值的时候,推荐使用self.语法 dot syntax//如self.count=number;
//直接写_count=number,直接赋值(指针指向他),但没有拥有权易出错
-(void)reSetNumber:(NSNumber *)number{
/*[_count release];
_count=[number retain];等同*/

self.count=number;
}
@end


四  init-dealloc内不能使用self



有些情况不能(尽量不能)用点语法的:如之前所讲的setter方法内 如本节说明的init/dealloc

在init/dealloc方法里面尽量不要使用点语法,大多数情况下无问题,当子类里面重写了父类的某个属性变量的setter方法时不能用。

原因:
init使用访问器方法导致第一种错误:
调用init方法初始化这个对象,当使用self.name,系统默认会去调用name的setter方法,在SuperMan类里面重写了setter方法,调用他的init方法的时候主动调用了setter方法,覆盖了父类的setter方法
子类有可能会覆盖父类的accessor方法,从而改变accesser方法的行为。
比如:
分别在大头儿子.m和Person.m中,

#import "datouerzi.h"

@implementation datouerzi
-(void)setName:(NSString *)name{
[super setName:@"hello"];
}
@end
-(instancetype)initWithName:(NSString *)name{
if (self=[super init]) {
self.name=@"Jack";
}
return self;
}
最后在源文件中使用,打印结果是hello

@autoreleasepool {
datouerzi *dt=[[datouerzi alloc]initWithName:@"peng"];
dt.name=@"大头儿子";

NSLog(@"dt.name:%@",dt.name);
}
不过构造方法是干啥使的。。。。有待考究啊啊啊啊啊啊

init使用访问器方法导致第二种错误:

在初始化这个对象的时候,数组没有创建好,向数组里面添加内容导致错误。(不好演示没有讲到)
五、循环引用

强引用和弱引用



循环引用



若都为retain,即两个强引用。要想释放掉Docu对象,要引用计数为0,要先把Page引用计数为0,释放Page才能释放掉doc,只有等Document释放掉cur才能,你等我我等你,都释放不了,形成了循环引用。

解决方式:解决循环引用的方式是大的强引用小的,小的弱引用大的

autorelease自动释放池
对象被自动释放池修饰,就会被扔到池里
//arc 优点1.在很大程度上消除了手动内存管理的负担同时省去了内存泄露和过度释放对象引起的繁琐操 2.效率高
//缺点: 1.部分流行的开源库还没有转为ARC 2.对应非ARC代码,会出现内存泄露
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: