美文网首页OC开发
为什么Objective-C对象存储在堆上而不是栈上

为什么Objective-C对象存储在堆上而不是栈上

作者: JonesCxy | 来源:发表于2018-03-14 11:20 被阅读61次

    一、什么是栈对象和堆对象

    在Objective-C中,对象通常是指一块有特定布局的连续内存区域。我们通常这样创建一个对象

    NSObject *obj = [[NSObject alloc] init];
    

    这行代码创建了一个NSObject类型的指针obj和一个NSObject类型的对象,obj指针存储在栈上,而其指向的对象则存储在堆上(堆对象)

    目前OC并不支持直接在栈上创建对象(栈对象),但可以通过如下方式间接的创建

    struct {
    Class isa;
    } fakeNSObject;
    fakeNSObject.isa = [NSObject class];
    
    NSObject *obj = (NSObject *)&fakeNSObject;
    NSLog(@"%@", [obj description]);
    

    二、栈对象优缺点

    1、优点

    • 速度
      在栈上创建对象是非常快的,因为很多东西在编译时就确定了,运行时分配空间几乎不耗时;相对而言在堆上创建对象就非常耗时。
    • 简单
      站对象的生命周期是确定的,对象出栈以后就会被释放,不会存在内存泄漏,但这同样也是栈对象的最大缺点。

    2、缺点

    • 生命周期固定
      OC变量有效范围是由“{}”包含的块来决定的,也就是说找对象的生命周期仅限于其所在的块里,出了块立马会被释放,一个对象被创建以后有可能会通过方法调用传递到别的方法,当找对象的创建方法返回时,栈对象会被一起pop出栈而释放,导致其没法在别处被继续持有。此时retain操作会失效,除非用copy方法在想持有该栈对象的地方重新拷贝一份属于自己的站对象。
      因此,栈对象会给对象的内存管理造成巨大的麻烦。
    • 空间
      现在操作系统的栈和线程绑定,而栈空间是有限的,具体如下:
    512 KB (secondary threads)
    8 MB (OS X main thread)
    1 MB (iOS main thread)
    

    因此对象如果都在栈上创建不太现实,而堆只要物理内存不警告可以无限使用。
    综合以上优缺点,OC选择用堆存储对象。

    三、真的没有对象吗

    实际上OC里的block却是栈对象,因此栈对象面临的问题在block身上一个都不少,但由于block是仅有的特殊对象,大家对他的特殊性都已经习惯了。
    另外,根据前面所说,栈对象的有效区域仅限于其所在的块,因此像下面的代码就无法输出期望的结果:

    void (^block)();
    if(x)
    {
    block = ^{ printf("x\n"); };
    }
    else
    {
    block = ^{ printf("not x\n"); };
    }
    block();
    

    原文链接:http://foggry.com/blog/2017/02/06/wei-shi-yao-objective-c-dui-xiang-cun-chu-zai-dui-shang-er-bu-shi-zhan-shang/

    相关文章

      网友评论

      • 王的for:block对象是有三种呢,全局区_NSGlobalBlock,堆区_NSMallocBlock,栈区_NSStackBlock

      本文标题:为什么Objective-C对象存储在堆上而不是栈上

      本文链接:https://www.haomeiwen.com/subject/zhtfqftx.html