OC中内存管理的一些问题

关键词:局部变量放在栈中,自动释放 开辟空间   释放空间

C中:char c[10];    char * p = (char *) malloc(10);  // 开辟的空间长度是10  p[0] = 'A'; ….. p[9] = 'G';  p[10] = 'H';  最终的字符串p中仍包含H这个字符。开辟的虽然是10个字节的空间,但之后被定义的字符仍能输出。

C中有重复释放的问题,有多个指针指向同一块内存空间,但只需释放一次。而在OC中有内存计数,可以释放多次,有几个指针指向同一空间就可以释放几次。

ARC:Automatic Reference Counting  自动释放

MRC:手动释放

内存释放之后对象还可以调用方法.    缓冲、野指针的问题

内存管理的方式:不需要时刻关注内存管理的引用计数。

谁创建[alloc(+1)]谁释放[release(-1)]。谁retain(+1)谁release(-1)。

深拷贝、浅拷贝   可变空间、不可变空间

copy可以深拷贝(对可变字符串)也可以是浅拷贝(对不可变字符串),mutableCopy只能是深拷贝。copy得到的是不可变空间,mutableCopy得到的可变空间。 copy用NSString接收,mutableCopy用NSMutableString接收。

当copy对不可变字符串进行拷贝的时候是浅拷贝,内存空间不变,当对可变字符串进行拷贝的时候是深拷贝,内存空间可变。

析构函数:释放成员变量  在对象释放之前。(在MRC中使用)

@property展开之后的三个东西:1.set方法 2.get方法 3.自动生成一个带下划线的成员变量。如:

@property (nonatomic, copy) NSString * name;

等效于:

-(void)setName:(NSString *)name{

    _name = name;

}

-(NSString *)name{

    return _name;

}

调用dealloc方法销毁内存。

MRC中property的使用:

析构函数dealloc是用来释放成员变量的,当成员变量是用copy、retain修饰的时候都要进行释放。

// 析构函数 释放成员变量

-(void)dealloc{

    

    self.name = nil;

    self.subjectsArr = nil;

    [super dealloc];

}

self.name = nil;有两个功能:1.释放内存 2.设置成空指针,防止野指针的出现。

在MRC中,只要用到alloc开辟空间,就要进行一次释放。且是谁创建谁释放。

Student * xiaoming = [[Student alloc] init];

        [xiaoming studying];

        //alloc进行释放

        [xiaoming release];

在不采用retain计数的时候,哪怕是两个指针指向同一块内存,只需进行一次release即可。没有成员变量不必重写析构函数。(本人刚开始时的记忆方式)

ARC和MRC的混编:

ARC和MRC的文件可以建在同一个工程中,只不过要做一些处理。 // 如何ARCMRC混编  步骤

        // 选中工程 -> Targets ->Build Phases -> Compile Sources

        // 找到此文件 在右侧Compile Flags (将内容改为  -fno-objc-arc)  

自动释放池:autoreleasepool(在MRC中)

有两种写法:1.@autoreleasepool{}  2. NSAutoreleasePool * pool = [NSAutoreleasePool alloc] init;   [pool release];   两种写法的效果是一样的。

在自动释放池中有一个方法叫自动释放autorelease,它不同于release这个方法,release被调用后,引用计数会立马减1,而autorelease没有立马这么快,它有一个延迟(同样有用),在未来(自动释放池释放后)某个时间对计数器做减1的操作。当自动释放池释放的时候,释放池内部的所有对象所占的内存才被释放。这是因为:自动释放池内部有一个特殊的数组,这个数组专门用来存储池子内部autorelease对象。当自动释放池释放的时候,会遍历这个数组,将里面的对象全部销毁。

MRC中有一个特殊的东西,那就是数组。

当将用alloc开辟空间创建的对象放入数组后,再对这些对象用release释放后,这些对象的计数器仍不为零。只有当数组销毁的时候,这些对象的计数器才会为零。这是因为往数组中添加对象的时候,数组对这些对象做了retain操作,再数组释放的时候,数组又对这些对象做了release的操作。不过这些操作也全是再内部进行操作,并不需要我们去操作。我们只要记得使用黄金法则进行内存管理就可以了。

(感觉用了ARC之后可以完全不去理会MRC了,ARC已经帮助我们全部完成了)

回忆前面讲到的单例:

static Math * myMath = nil;

@implementation Math


// 创建对象的另外一种使用:单例的形式

+(Math *)createMath

{

    if(myMath == nil){

        myMath = [[Math alloc] init];

    }

    return myMath;

}

单例是类方法的特殊使用。

现在实现上方定义一个静态变量:

static Phone * phone = nil;


// 单例

+(Phone *)sharedPhone

{

    if(phone == nil){

        phone = [[Phone alloc] init];

    }

    return phone;

}


// 单例的使用

        Phone * sanxing = [Phone sharedPhone];

        NSLog(@"sanxing %p", sanxing); // 直接输出的是对象的地址

单例可以防止多处被实例化。即不能用alloc来开辟空间存储对象。(感觉还不是很明白)



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值