Objective-C基础2:内存管理基础

1.内存存储区域

C、C++里面。栈区:存储临时变量和对象。堆区域:存储动态分配对象。静态变量存储区:存储静态变量和常量对象。

OC里面的内存存储区域跟C、C++一样。

2.为什么要进行内存管理

写过C、C++程序的都知道,内存管理永远是C++程序的一大痛点,项目当中崩溃全部来自于内存相关的操作,尤其是指针操作和内存操作,稍不注意就会产生内存访问违规造成程序崩溃。那么如何进行内存管理呢,个人认为有以下几点原则:尽量用系统提供给我们的封装对象,不要用原生的,比如用string而不要用char*,用string能避免项目中大部分的字符串违规操作;能在栈上分配就不在堆上分配,利用栈的自动释放功能帮我们释放;对于复杂的内存操作比如多个类或者多个线程引用同一块内存,那就给这块内存加引用计数;内存操作一定要判空操作。

我们知道OC中的所有对象都是动态分配的,那么OC中是如何管理这些对象的呢?答案是利用引用计数来管理。

3.OC中对象内存管理

OC中通过引用计数来管理对象的生命周期。

- (instancetype)retain OBJC_ARC_UNAVAILABLE;  //引用加1

- (oneway void)release OBJC_ARC_UNAVAILABLE; //引用减1

- (instancetype)autorelease OBJC_ARC_UNAVAILABLE; //自动释放对象

- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE; //返回当前的引用技术

当对象B拥有对象A时,设置对象A时,最好掉用Retain提升引用计数,在dealloc方法里面减少引用技术。

注意下面代码的中(void) setA : (A*) pAIn实现

-(void) setA : (A*) pAIn

{

[pAIn retain];

[pA release];

pA = pAIn;

}

先保留PAIn,再释放PA,然后赋值,这种写法能有效地避免PAIn和PA指向同一对象这种情况,强烈建议一定要这样写。

代码如下:

@interface A : NSObject

- (void) disInfo;
@end

@implementation A

- (void) disInfo
{
    NSLog(@"I‘m A haha!");
}

@end

@interface B : NSObject
{
@private
    A* pA;

}

-(void) setA : (A*) pAIn;
-(void) disA;

@end

@implementation B

- (void)dealloc
{
    [pA release];
    [super dealloc];
}

-(void) setA : (A*) pAIn
{
    [pAIn retain];
    [pA release];
    pA = pAIn;
}

-(void) disA
{

    [pA disInfo];

}

@end

int main(int argc, const char * argv[]) {

    A* pA = [A new];
    B* pB = [B new];
    [pB setA:pA];
    [pB disA];
    [pB release];
    [pA release];
    return 0;
}

上面的例子中我们需要手动地掉用retain和release方法,也就是说我们需要知道何时要retain,何时需要release,很显然在业务逻辑很复杂的情况下需要追踪引用计数造成的问题需要花费比较多的时间。那么,如何让对象自动retain和release呢?写过Windows Com程序的人知道CComPtr这个智能指针类,OC又是如何做的呢?下面揭晓。

4.OC中自动释放内存

Cocoa中的自动释放池@autoreleasepool和NSAutoreleasepool配合对象的autorelease方法来实现自动释放内存。

1)利用autoreleasepool和autorelease。代码如下:

    @autoreleasepool
    {
        A* pA = [A new];
        [pA autorelease];
        B* pB = [B new];
        [pB autorelease];
        [pB setA:pA];
        [pB disA];
    }

上面的代码跟3中的代码相比优势在:在pA和pB创建完成之后直接调用autorelease方法将对象加入自动释放吃,代码紧凑,后面再也不用担心在什么时候release了。

2)利用NSAutoreleasePool和autorelease。代码如下:

 NSAutoreleasePool* pool = [NSAutoreleasePool new];
    A* pA = [A new];
    [pA autorelease];
    B* pB = [B new];
    [pB autorelease];
    [pB setA:pA];
    [pB disA];
    [pool release];

代码跟跟利用关键字@autoreleasepool的代码差不多。

那么面对着两种方式,我们应该选择哪种呢?个人认为有一下几种原则:

1)对于对象操作紧凑的代码用@autoreleasepool,因为他的效率比NSAutoreleasePool高

2)对象A拥有一些例对象并且这些对象保留在NSArray等数组中,用 NSAutoreleasePool,因为只需要在A的dealloc对象当中调用NSAutoreleasePool的release方法,保存在NSArray的对象就会自动释放,很显然@autoreleasepool不具备这样的能力。

时间: 2024-10-29 04:18:01

Objective-C基础2:内存管理基础的相关文章

.NET基础拾遗(1)类型语法基础和内存管理基础2

二.内存管理和垃圾回收 2.1 .NET中栈和堆的差异? 每一个.NET应用程序最终都会运行在一个OS进程中,假设这个OS的传统的32位系统,那么每个.NET应用程序都可以拥有一个4GB的虚拟内存..NET会在这个4GB的虚拟内存块中开辟三块内存作为 堆栈.托管堆 以及 非托管堆. (1).NET中的堆栈 堆栈用来存储值类型的对象和引用类型对象的引用(地址),其分配的是一块连续的地址,在.NET应用程序中,堆栈上的地址从高位向低位分配内存,.NET只需要保存一个指针指向下一个未分配内存的内存地址

.NET基础拾遗(1)类型语法基础和内存管理基础

一.基础类型和语法 1.1 .NET中所有类型的基类是什么? 在.NET中所有的内建类型都继承自System.Object类型.在C#中,不需要显示地定义类型继承自System.Object,编译器将自动地自动地为类型添加上这个继承申明,以下两行代码的作用完全一致: public class A { } public class A : System.Object { } 1.2 值类型和引用类型的区别? 在.NET中的类型分为值类型和引用类型,它们各有特点,其共同点是都继承自System.Ob

类型语法基础和内存管理基础

一:基础类型和语法 1.1 .net中所有类型的基类是什么: 在.net中所有的内建类型都继承System.Object类型.C#中编译器自动添加继承申明 public class A{} public class A:System.Object{} 1.2 值类型和引用类型的区别 .net中分值类型和引用类型,都继承自System.Object,区分标准是否继承System.ValueType(继承自System.Object), 继承自System.VauleType的类型的是值类型(整型,

.NET基础拾遗(1)类型语法基础和内存管理基础1

一.基础类型和语法 1.1 .NET中所有类型的基类是什么? 在.NET中所有的内建类型都继承自System.Object类型. 1.2 值类型和引用类型的区别? 在.NET中的类型分为值类型和引用类型,它们各有特点,其共同点是都继承自System.Object,但最明显的区分标准却是是否继承自System.ValueType(System.ValueType继承自System.Object),也就是说所有继承自System.ValueType的类型是值类型,而其他类型都是引用类型.常用的值类型

基础拾遗类型语法基础和内存管理基础

http://www.zfs.cn/home.php?mod=space&uid=674359 http://www.zfs.cn/home.php?mod=space&uid=674360 http://www.zfs.cn/home.php?mod=space&uid=674361 http://www.zfs.cn/home.php?mod=space&uid=674363 http://www.zfs.cn/home.php?mod=space&uid=67

Objective-C基础3:内存管理续

1.上篇我们讲了OC中的内存管理基础,我们再总结一下何时该用内存管理.1)当用new.alloc.copy创建对象时,必须要释放对象. 2)当拥有对象时,如果是临时对象,不需要释放:当需要长时间保留对象时,必须保留对象并且在dealloc方法中释放对象. 2.OC中的垃圾回收机制 OC2.0引入了垃圾回收机制,也就是启用了垃圾回收机制之后,我们忘记了释放对象,OC会帮我们释放对象,这点可看出OC比C++的强大之处了. 垃圾回收机制主要原理是在运行中定时动态跟踪对象,检查对象的引用技术并且进行清理

计算机操作系统学习笔记_7_内存管理 --内存管理基础

h2.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }h2.cjk { font-family: "微软雅黑"; font-size: 16pt; }h2.ctl { font-family: "AR PL UMing CN"; font-size: 16pt; }h1 { margin-bottom: 0.21cm; }h1.western { fon

蓝懿-打飞机图片,内存管理基础 刘国斌老师

一 图片 1背景图片 因为是两张相同图片不断重复出现  开始时瞬间加载 用for(int i=0,i<2,i++)   开timer实现动作 2飞行效果 是两张图片出现一个位置 长时间变换加载 开timer int count; count++: if(count%2=0){ self.image=[uiimage imagenamed:@"1"]} else{ self.image=[uiimage imagenamed:@"2"]} 3爆炸效果 多张图片按

java基础---JVM内存管理以及内存运行机制学习总结

自己从网上搜资料拼接了一张JVM内存图:如下图所示: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改