OC中内存管理的一些问题


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/46944979

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

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的文件可以建在同一个工程中,只不过要做一些处理。 // 如何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来开辟空间存储对象。(感觉还不是很明白)

优质内容筛选与推荐>>
1、在sqlserver视图中慎用table.*的方式。
2、《node.js开发指南》第五章与新版Node变化太大的一些问题
3、Sprite Sheet的大概理解
4、软件工程个人作业01
5、qq开放平台可以应用到网页游戏的api整理


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号