Block(二)内存管理与其他特性-b
一、block放在哪里
我们针对不同情况来讨论block的存放位置:
1.栈和堆
以下情况中的block位于堆中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void foo() { __block int i = 1024 ; int j = 1 ; void (^blk)( void ); void (^blkInHeap)( void ); blk = ^{ printf( "%d, %d\n" , i, j);}; //blk在栈里 blkInHeap = Block_copy(blk); //blkInHeap在堆里 } - ( void )fooBar { _oi = 1 ; OBJ1* oj = self ; void (^oblk)( void ) = ^{ printf( "%d\n" , oj.oi);}; void (^oblkInHeap)( void ) = [oblk copy ]; //oblkInHeap在堆中 } |
2.全局区
以下情况中的block位于全局区:
1
2
3
4
5
6
7
8
9
10
|
static int (^maxIntBlock)( int , int ) = ^( int a, int b){ return a>b?a:b;}; - ( void )fooBar { int (^maxIntBlockCopied)( int , int ) =[maxIntBlock copy ]; } void foo() { int (^maxIntBlockCopied)( int , int ) = Block_copy(maxIntBlock); } |
需要注意的是,这里复制过后的block依旧位于全局区,实际上,复制操作是直接返回了原block对象。
二、block引用的变量在哪里
1.全局区
全局区的变量存储位置与block无关:
1
2
3
4
5
6
7
8
|
static int gVar = 0 ; //__block static int gMVar = 1; void foo() { static int stackVar = 0 ; // __block static int stackMVar = 0; } |
注意,static变量是不允许添加__block标记的
2.堆栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void foo() { __block int i = 1024 ; //此时i在栈上 int j = 1 ; //此时j在栈上 void (^blk)( void ); blk = ^{printf( "%d, %d\n" , i, j); }; //此时,blk已经初始化,它会拷贝没有__block标记的常规变量自己所持有的一块内存区,这块内存区现在位于栈上,而对于具有__block标记的变量,其地址会被拷贝置前述的内存区中 blk(); //1024, 1 void (^blkInHeap)( void ) = Block_copy(blk); //复制block后,block所持有的内存区会被拷贝至堆上,此时,我们可以说,这个block现在位于堆上 blkInHeap(); //1024,1 i++; j++; blk(); //1025,1 blkInHeap(); //1025,1 } |
让我们一步步剖析:
首先,我们在栈上创建了变量ij,并赋予初始值,然后创建一个block变量名为blk,但未赋值。
然后我们初始化这个blk,赋值为一个只有一句printf的block,值得注意的是,一个block一旦创建,其引用到的常规变量会进行如下操作:
没有__block标记的变量,其值会被复制一份到block私有内存区
有__block标记的变量,其地址会被记录在block私有内存区
然后调用blk,打印1024, 1很好理解
接下来复制blk到堆,名曰blkInHeap,调用之,打印1024, 1也很好理解
接下来我们为ij增值,使其变为1025和2,此时再调用blk或者blkInHeap,会发现结果为1025, 1,这是因为变量j早已在创建原始的block时,被赋值进block的私有内存区,后续对i的操作并非操作的私有内存区的复制品,当调用blk或者blkInHeap时,其打印使用的是私有内存区的复制品,故而打印结果依旧为1;而变量j的修改会实时生效,因为block记录的是它的地址,通过地址来访问其值,使得外部对j的修改在block中得以生效。对于变量i来讲,可算是物是人非吧?
因此,无论j++这一句放到blk()这句之前或者之后,只要它位于block初始化之后,这段代码执行的控制台打印结果都会是:1024, 1。而不是1024, 2(假设不调用i++)
Block(二)内存管理与其他特性-b的更多相关文章
- Block介绍(二)内存管理与其他特性
我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题.这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因. 一.block放在哪里 我们针对不同情 ...
- iOS中Block介绍(二)内存管理与其他特性
我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题.这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因. 一.block放在哪里 我们针对不同情 ...
- block之---内存管理
首先简单说下MRC和ARC MRC: 手动管理内存,需要自己去释放内存, 如果对象的引用计数器为0时对象就会被释放. 属性修饰策略:assign, retain, copy ARC: ARC是编译器特 ...
- Android笔记--Bitmap(二)内存管理
Bitmap(二) 内存管理 1.使用内存缓存保证流畅性 这种使用方式在ListView等这种滚动条的展示方式中使用最为广泛, 使用内存缓存 内存缓存位图可以提供最快的展示.但代价就是占用一定的内存空 ...
- Block(二)内存管理与其他特性
一.block放在哪里 我们针对不同情况来讨论block的存放位置: 1.栈和堆 以下情况中的block位于堆中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- Spark(二): 内存管理
Spark 作为一个以擅长内存计算为优势的计算引擎,内存管理方案是其非常重要的模块: Spark的内存可以大体归为两类:execution和storage,前者包括shuffles.joins.sor ...
- cocos2d-x游戏引擎核心之二——内存管理
(一) cocos2d-x 内存管理 cocos2d里面管理内存采用了引用计数的方式,具体来说就是CCObject里面有个成员变量m_uReference(计数); 1, m_uReference的变 ...
- block没那么难(二):block和变量的内存管理
本系列博文总结自<Pro Multithreading and Memory Management for iOS and OS X with ARC> 了解了 block的实现,我们接着 ...
- iOS Block 内存管理的探讨
在很多情况下Block是造成程序循环引用内存泄漏的元凶.下面我们就讲解一下block对内存管理的影响.在讲解之前.希望大家对block有一定的了解.如果大家还不是太清楚block的实现原理.希望大家可 ...
随机推荐
- CXF实战之拦截器Interceptor(四)
拦截器(Interceptor)是CXF功能最基本的扩展点,能够在不正确核心模块进行改动的情况下.动态加入非常多功能.拦截器和JAX-WS Handler.Filter的功能相似,当服务被调用时.就会 ...
- LintCode: Restore IP Address
C++ string::substr(start_pos, length) vector::push_back(element) class Solution { public: vector< ...
- ZH奶酪:AngularJS/JavaScript上传图片【PC端】
[功能介绍] 类似与修改个人信息的时候,点击头像,就可以完成选择照片.上传照片等步骤达到替换头像的目的. [运行流程] (1)点击头像 (2)选择头像 (3)点击“完成”,上传头像 1.HTML图片部 ...
- VS2015 之 常用快捷键
调试执行 F5,终止调试执行 Shift+F5 启动执行 Ctrl+F5 查找下一个 F3,查找上一个 Shift+F3 附加到进程 Ctrl+Alt+P,逐过程 F10,逐语句执行 F11 切换断点 ...
- VS2015 之 多行缩进
VS2015工具栏缺少“多行缩进工具”,经查阅资料总结如下: 首先,选中需要缩进的行代码: 1.增大缩进:“Tab”键 2.减小缩进:“Shift”键 + “Tab”键
- postman发送get请求
在地址栏里输入请求url(用到拼接方式):http://127.0.0.1:8081/getuser?userid=1 选择“GET”方式, 点击“send”得到json数据如图 分类: post ...
- Canvas动画 位图缓存提高效率和对应的内存问题
对一个矢量图动画,开启位图缓存能大大提高运行效率.所谓开启位图缓存,其实要自己动手,先创建一个临时canvas,然后把矢量图绘制到这个canvas上,到了实际绘制时,直接把这个临时canvas拷贝到真 ...
- 〖Linux〗Kubuntu KDE开机后总是提示“system program problem detected”的解决方法
自从从Ubuntu切换到了Kubuntu之后,就经常在开机的时候提示“system program problem detected”: 查看 /var/crash/ 发现都是一些无关痛痒的程序在关机 ...
- 源代码解析Android中View的layout布局过程
Android中的Veiw从内存中到呈如今UI界面上须要依次经历三个阶段:量算 -> 布局 -> 画图,关于View的量算.布局.画图的整体机制可參见博文 < Android中Vie ...
- SpringCloud之搭建配置中心
一.搭建config-server 1.引入pom <dependencies> <dependency> <groupId>org.springframework ...