前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OC中内存管理的一些问题

OC中内存管理的一些问题

作者头像
用户1451823
发布2018-09-13 17:21:54
6900
发布2018-09-13 17:21:54
举报
文章被收录于专栏:DannyHoo的专栏DannyHoo的专栏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1338195

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

C中:char c10;    char * p = (char *) malloc(10);  // 开辟的空间长度是10;  p0 = 'A'; ….. p9 = 'G';  p10 = '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的文件可以建在同一个工程中,只不过要做一些处理。 // 如何ARC和MRC混编  步骤:

// 选中工程 -> 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来开辟空间存储对象。(感觉还不是很明白)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年07月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档