详解Block: block循环引用

http://yidaizhenlong.farbox.com/post/2014-11-25#content

详解Block: block循环引用

2014-11-25 10:40

我们在block中,遇到引用外部变量,一般习惯性的给这个变量加个block 和weak 。比如block中用到self,一般都会这样写,

__block __typeof(self) weakSelf = self;

那是不是所有的block都要用这样写的。这样写固然万无一失吧,但是面试的时候别人问你,你就懵了,看下面代码

void (^TestBlock)(void) = ^{
        NSLog(@"test:%@", self);
    };
    TestBlock();

如果面试者问你,这个TestBlock里面的self,是否会被循环引用呢,为什么?

答案是不会?为什么呢?这要从block的三种类型说起。根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。
NSGlobalBlock:类似函数,位于text段;
NSStackBlock:位于栈内存,函数返回后Block将无效;
NSMallocBlock:位于堆内存。
NSGlobalBlock如下,我们可以通过是否引用外部变量识别,未引用外部变量即为1.NSGlobalBlock,可以当做函数使用。

float (^sum)(float, float) = ^(float a, float b){

        return a + b;
    };

    NSLog(@"block is %@", sum); //block is <__NSGlobalBlock__: 0x47d0>

2.NSStackBlock,前提是MRC环境,arc

void (^TestBlock)(void) = ^{
        NSLog(@"test:%@", self);
    };
NSLog(@"block is %@", ^{
        NSLog(@"test:%@", self);
    });
    //block is <__NSStackBlock__: 0xbfffdac0>
    //打印可看出block是一个 NSStackBlock, 即在栈上, 当函数返回时block将无效

    NSLog(@"block is %@", TestBlock);
    //block is <__NSMallocBlock__: 0x75425a0>
    //上面这句在非arc中打印是 NSStackBlock, 但是在arc中就是NSMallocBlock
    //即在arc中默认会将block从栈复制到堆上,而在非arc中,则需要手动copy.

3.NSMallocBlock只需要对NSStackBlock进行copy操作就可以获取
所以说block的循环引用问题,是因为block在拷贝到堆上的时候,会retain其引用的外部变量,那么如果block中如果引用了他的宿主对象,即self,就会能引起循环引用。
留个问题,BLOCK被另一个BLOCK使用时,另一个BLOCK被COPY到堆上时,被使用的BLOCK此时会被copy吗?其参数的BLOCK是否会发生COPY的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MATLAB中,for循环是一种常用的循环语句,主要用于重复执行一段代码,直到满足某个条件为止。for循环通常包含一个循环变量循环范围和循环体三个部分。 for循环的基本语法为: ``` for 循环变量 = 循环范围 循环体 end ``` 其中,循环变量是一个变量循环范围是一个数组或向量,循环体是需要执行的代码。for循环按照循环范围中元素的顺序依次执行循环体。 例如,以下代码使用for循环输出1到10的整数: ``` for i = 1:10 disp(i) end ``` 在这个例子中,循环变量i从1到10依次取值,每次循环执行disp(i),即输出i的值。 在for循环中,循环范围可以是一个向量或矩阵。如果循环范围是一个向量,则循环变量依次取向量中的每个元素;如果循环范围是一个矩阵,则循环变量按照列优先的顺序依次取矩阵中的每个元素。 例如,以下代码使用for循环计算一个3x3矩阵的行和: ``` A = [1 2 3; 4 5 6; 7 8 9]; row_sum = zeros(1, 3); for i = 1:3 for j = 1:3 row_sum(i) = row_sum(i) + A(i, j); end end disp(row_sum) ``` 在这个例子中,外层循环变量i取值为1到3,内层循环变量j也取值为1到3,每次内层循环将A(i,j)加到row_sum(i)中,最终得到每行的和。 除了基本语法外,for循环还支持break和continue语句。break语句用于跳出循环,continue语句用于跳过本次循环。 例如,以下代码使用for循环输出1到10的整数,但跳过偶数: ``` for i = 1:10 if mod(i, 2) == 0 continue end disp(i) end ``` 在这个例子中,如果i是偶数,则跳过本次循环,否则输出i的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值