• OC 中的block存储位置


    以下所有在ARC情况下:

    一、block块的存储位置(block块入口地址):可能存放在2个地方:代码区、堆区(程序分5个区,还有常量区、全局区和栈区,对于MRC情况下代码还可能存在栈区。关于分区详细参考:http://www.cnblogs.com/mddblog/p/4405165.html)。

    详细介绍:

    情况1:代码区

        不访问处于栈区的变量(例如局部变量),且不访问处于堆区的变量(例如alloc创建的对象)。也就是说访问全局变量也可以。

    /**
      没有访问任何变量
     */
    int main(int argc, char * argv[]) {
        void (^block)(void) = ^{
            NSLog(@"===");
        };
        block();
    }
    /**
      访问了全局(静态)变量
     */
    int  iVar = 10;
    int main(int argc, char * argv[]) {
        void (^block)(void) = ^{
            NSLog(@"===%d",iVar);
        };
        block();
    }

    情况2:堆区

        如果访问了处于栈区的变量(例如局部变量),或处于堆区的变量(例如alloc创建的对象)。都会存放在堆区。(实际是放在栈区,然后ARC情况下自动又拷贝到堆区)

    /**
      访问局部变量
     */
    int main(int argc, char * argv[]) {
        int iVar = 10;
        void (^block)(void) = ^{
            NSLog(@"===%d",iVar);
        };
        block();
    }

    二、代码存放在堆区时,就需要特别注意,因为堆区不像代码区不变化,堆区是不断变化的(不断创建销毁)。因此代码有可能会被销毁(当没有强指针指向时),如果这时再访问此段代码则会程序崩溃。因此,对于这种情况,我们在定义一个block属性时应指定为strong,或copy:

    @property (nonatomic, strong) void (^myBlock)(void); // 这样就有强指针指向它

    @property (nonatomic, copy)  void (^myBlock)(void);  // 并不会在堆区copy一份,原因见 三

    而对于第一种情况(代码存在代码区),使用strong,copy(不会复制一份到堆区)也可以。因此定义block时最好指定为strong(推荐)或copy。

    三、指定为copy后是否会拷贝一份呢?(或者说是浅拷贝还是深拷贝)

            1 copy可变变量:在赋值指针的同时也会复制指针指向的内存区域。深拷贝,例如NSMutableString对象。

            2 copy不可变变量:等同于strong,还是浅拷贝,例如NSString对象。

        因为block是一段代码,即不可变的,所以并不会深拷贝。

  • 相关阅读:
    OpenCV 学习笔记(1-1)opecv3.41及其扩展库在VS2015下配置
    OpenCV 学习笔记(11)像素级别指针操作
    (19) 树莓派发送微信消息
    mybatis+spring配置
    spring Ioc 实践
    运用BufferedWriter把数据写入文件
    【转】跟我一起学Spring 3(4)–深入理解IoC(控制反转)和DI(依赖注入)
    [转]Spring MVC之@RequestMapping 详解
    python错误处理
    python函数
  • 原文地址:https://www.cnblogs.com/mddblog/p/4413166.html
Copyright © 2020-2023  润新知