4.Block的类型

类型分为:

_NSConcreteGlobalBlock(全局块)

_NSConcreteStackBlock(栈块)

_NSConcreteMallocBlock(堆块)

栈区(stack):由系统自动分配,一般存放函数参数值、局部变量的值等。由编译器自动创建与释放。其操作方式类似于数据结构中的栈,即后进先出、先进后出的原则。

例如:在函数中申明一个局部变量int b;系统自动在栈中为b开辟空间。

堆区(heap):一般由程序员申请并指明大小,最终也由程序员释放。如果程序员不释放,程序结束时可能会由OS回收。对于堆区的管理是采用链表式管理的,操作系统有一个记录空闲内存地址的链表,当接收到程序分配内存的申请时,操作系统就会遍历该链表,遍历到一个记录的内存地址大于申请内存的链表节点,并将该节点从该链表中删除,然后将该节点记录的内存地址分配给程序。

分别举3个列子

typedef void (^blk_t) ();

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

blk_t block = ^{

printf("I'm just a block\n");

};

block();

return 0;

}

这种是   _NSConcreteGlobalBlock 全局

typedef void (^blk_t) ();

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

int i = 1;

blk_t block = ^{

printf("%d\n",i);

};

block();

return 0;

}

这种 是 堆块

typedef void (^blk_t) ();

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

int i = 1;

__weak blk_t block = ^{

printf("%d\n",i);

};

block();

return 0;

}

这种是 栈块

总结如下:

记述全局变量的地方创建的Block,这种是全局的

不截获自动变量的时候将会被编译器编译为_NSConcreteGlobalBlock.

进行了copy操作(实质上是调用_Block_copy函数),会让块从栈复制到堆上.

调用Block的copy实例方法,会把栈上的block复制到堆上.

将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时是在堆上的

Block作为函数返回值时是在堆上

Block的copy,retain,release操作

对block retain操作并不会改变引用计数器,retainCount ,始终为1

NSGlobalBlock:retain、copy、release操作都无效;

Block_copy与copy等效,Block_release与release等效

NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的 错误是[[mutableAarry addObject:stackBlock],在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将stackBlock copy到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。

NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain

尽量不要对Block使用retain操作

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python3

Python语句-if.....else......

似乎所有的条件语句都使用if.....else.....,它的作用可以简单地概括为非此即彼,满足条件A则执行A的语句,否则执行B语句,python的if.......

982
来自专栏从零开始学 Web 前端

09 - JavaSE之线程

PS: 如果我们没有 new一个 Thread 对象出来,而是直接使用 MyThread 的 run 方法(mt.run()),这就是方法调用,而不是启动线程了...

1315
来自专栏Android开发指南

7:多线程

2968
来自专栏数据结构与算法

3185 队列练习 1

3185 队列练习 1 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给定一...

3026
来自专栏技术小站

编程填空:第i位替换 编程填空:第i位取反 编程填空:左边i位取反

写出函数中缺失的部分,使得函数返回值为一个整数,该整数的第i位和m的第i位相同,其他位和n相同。

2031
来自专栏菜鸟计划

angularjs promise详解

一、什么是Promise Promise是对象,代表了一个函数最终可能的返回值或抛出的异常,就是用来异步处理值的。 Promise是一个构造函数,自己身上有al...

2975
来自专栏Felix的技术分享

JVM的简单实现

1637
来自专栏博岩Java大讲堂

Java虚拟机--线程上下文类加载器

2324
来自专栏Java编程技术

并发队列-无界非阻塞队列ConcurrentLinkedQueue原理探究

常用的并发队列有阻塞队列和非阻塞队列,前者使用锁实现,后者则使用CAS非阻塞算法实现,使用非阻塞队列一般性能比较好,下面就看看常用的非阻塞ConcurrentL...

1211
来自专栏海天一树

小朋友学C++(16):C++创建对象的3种方式

先看程序: #include <iostream> using namespace std; class A { private: int n; pub...

3618

扫码关注云+社区

领取腾讯云代金券