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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

病毒

【问题描述】   有一天,小y突然发现自己的计算机感染了一种病毒!还好,小y发现这种病毒很弱,只是会把文档中的所有字母替换成其它字母,但并不改变顺序,也不会增加...

5377
来自专栏haifeiWu与他朋友们的专栏

System方法总结

最近在研究Android源码,突然看到有很多和System有关,什么System.arraycopy、System.nanoTime(),所以专门花时间看了一下...

1032
来自专栏技术总结

《Objective-C高级编程》温故知新之"自动引用计数"

1、使用alloc、new、copy、mutableCopy的意味着自己生成的对象只有自己持有

1295
来自专栏蘑菇先生的技术笔记

clojure基础入门(一)

2774
来自专栏个人分享

工程开发实用类与方法总结(未完)

1 .checkArgument(boolean) :   功能描述:检查boolean是否为真。 用作方法中检查参数   失败时抛出的异常类型: Illeg...

1093
来自专栏老九学堂

十七个C语言新手编程时常犯的错误及解决方式

编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。

1574
来自专栏iOS 开发杂谈

iOS RunTime之二:数据结构

由上面一章中,我们了解了什么是RunTime,RunTime用来做什么,下面了解一下Runtime数据结构。

1802
来自专栏蘑菇先生的技术笔记

clojure基础入门(一)

1513
来自专栏xx_Cc的学习总结专栏

iOS底层原理总结 - 探寻block的本质(二)

2894
来自专栏绿巨人专栏

[Java] 设计模式: Code Shape - 管理你的代码结构

942

扫码关注云+社区

领取腾讯云代金券