博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Block(二)内存管理与其他特性-b
阅读量:6117 次
发布时间:2019-06-21

本文共 2039 字,大约阅读时间需要 6 分钟。

一、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++)

转载地址:http://ucvka.baihongyu.com/

你可能感兴趣的文章
WM8962 HPOUT 信号强度 时间周期
查看>>
[家里蹲大学数学杂志]第432期Hardy type inequalities
查看>>
Spring MVC 4.2 CORS 跨域访问
查看>>
小计生产数据库事故--缺少where的update
查看>>
谁偷走了我们的时间?
查看>>
[20170410]11G ora_sql_txt是否有效.txt
查看>>
CoreThink 之 Git 模块 v1.1.2 支持二级域名
查看>>
《Unity 3D人工智能编程》——第1章 人工智能导论
查看>>
《Linux 设备驱动开发详解(第2版)》——1.3 有操作系统时的设备驱动
查看>>
《数据库技术原理与应用教程(第2版)》——1.5 数据管理的变迁
查看>>
《CMOS集成电路后端设计与实战》——1.2 国内集成电路发展现状
查看>>
《拥抱机器人时代——Servo杂志中文精华合集》——第3章 智能连接:欢迎来到物联网的世界...
查看>>
微软 IIS 服务器的市场占有率接近 Apache
查看>>
mongodb授权登录,经过自己修改后的授权登录方式
查看>>
Windows 原生运行 Linux 的技术细节
查看>>
《Abaqus GUI程序开发指南(Python语言)》——2.12 文件的操作
查看>>
《Adobe Premiere Pro CC经典教程》——第14 课 颜色校正和分级 14.1 开始
查看>>
Nologging到底何时才能生效?
查看>>
SoftEther ***
查看>>
我的友情链接
查看>>