block_blockingqueue - CSDN
精华内容
参与话题
  • 又见block(一):block是什么?

    千次阅读 2018-09-10 00:01:08
    block的原理实质问题是一道分水岭,区分中高级程序的试金石,一般的大公司,他可能不会问你内存管理甚至多线程编程与简单的一笔带过,但是block一定会仔细问。无奈的是平时只知使用,对其原理与实质没有深究,因此数...
    block的原理是一道分水岭,区分中高级程序的试金石,一般的大公司,他可能不会问你内存管理,甚至多线程编程问题也简单的一笔带过,但是block一定会仔细问。可惜的是平时只知使用,对其原理与实质没有深究,因此数次面试倒在这道坎上,真是心有不甘,这次好好理理关于block的前因后果,以供后续随手翻阅查证。

    block的定义:带有自动变量(局部变量)的匿名函数

    想要说明什么是匿名函数,先来了解下什么是函数以及函数指针

    • 函数:函数是C语言程序中的重要组成部分,不同函数调用的组合实现程序的各个功能。
      格式如下:
        returnType funcName(paramter List){
            //funcBody
        }

    returnType:函数返回值
    funcName:函数名
    paramter List:参数列表
    funcBody:函数体
    一个简单的函数如下:

        int funcSum (int count) {
            return count + 10;
        }

    定义了一个名为funcSum的函数,有一个int类型的形参,返回值是int类型
    函数调用如下:

        int result = funcSum(18);
    • 函数指针:除了直接调用函数之外,我们还可以定义一个函数指针来指向这个函数地址,通过调用函数指针进而调用指向的函数,函数指针的定义如下:
        returnType (*FuncPointer)(Paramter List)

    继续上面定义的funcSum函数,现在定一个函数指针指向这个函数

        int*funcPointer)(int)= &funcSum;

    调用函数指针方式如下:

        int result = (*funcPointer)(18);

    通过函数指针可以来调用函数,但是在给函数指针赋值的过程中,依然用到了函数名,因此在C语言中要想调用函数,无论是直接调用还是通过函数指针来调用都无法绕过函数名。

    但是OC中的block,就可以使用不带函数名称的函数,即匿名函数,被看着是C语言的扩充功能。

    在了解什么是匿名函数后,再来说说“带有自动变量(局部变量)”是什么意思?
    变量的类型以及存储位置

    • 全局变量:全局静态区
    • 全局静态变量:全局静态区
    • 局部静态变量:栈
    • 局部变量:栈
      内存分布
      局部变量:包括静态局部变量都是存在栈中的,超过作用域后就会被销毁
      全局变量:包括全局静态变量,既不是存在栈中,也不是存在堆中,而是存放在“全局区/静态区”,占用静态的存储单元

    block做为匿名函数,不但能访问全局变量,更重要的是拥有捕获函数外局部变量的功能,一般情况下,block中访问一个外部局部变量,block会持用它的临时状态,自动捕获变量值,捕获后修改外部的局部变量不会影响block内部捕获的状态
    比较经典的例子:

        int val = 23;
        void (^block) (void) = ^{
            NSLog(@"val = %d",val);
        };
        val = 2;
        block();

    代码输出为:val = 23,不是2
    block在定义实现时,就会对它捕获的外部局部变量进行一次只读拷贝,然后在block中使用该只读拷贝,即外部局部变量的副本,所以block外部修改局部变量,对其内部的副本无影响,就是说block捕获的是局部变量的瞬时值
    那么这种情况下能否在block内对局部变量val值进行修改呢?尝试报错截图如下:
    这里写图片描述
    根据错误提示,我们修改代码如下

        __block int val = 23;
        void (^block) (void) = ^{
            NSLog(@"val = %d",val);
        };
        val = 2;
        block();

    代码输出结果为:val = 2,并且此时可以在block中修改外部的局部变量值


    为什么在局部变量定义前加__block就能在block中修改捕获的局部变量值了,后面再继续分析,本节完,待续……

    参考文章
    又见block(二):block语法定义
    又见block(三):block实质
    又见block(四):block捕获自动变量
    又见block(五): __block变量和对象
    又见block(六):block存储域与__block变量存储域
    又见block(七):截获对象

    展开全文
  • block 解析 - 静态变量

    2019-07-17 05:22:00
    上一篇我们了解了block全局变量的使用,静态变量和全局变量一样,可以直接在block内部使用,也可以在block内部修改 引用官方文档: Global variables are accessible, including static variables that exist ...

    静态变量

    上一篇 我们了解了block全局变量的使用,静态变量和全局变量一样,可以直接在block内部使用,也可以在block内部修改

    引用官方文档:

    Global variables are accessible, including static variables that exist within the enclosing lexical scope.

    我们来看一段代码:

    声明一个静态变量,在block内部修改

    static NSString * _para1;
    -(void )test4
    {
        _para1=@"para1";
        //初始值
        NSLog(@"init para1:%@,%p,%p",_para1,&_para1,_para1);
        void (^myBlock)(int) = ^(int num) {
            //block内赋值
            _para1=@"para3";
            NSLog(@"excuteing para1:%@,%p,%p",_para1,&_para1,_para1);
        };
        //修改前赋值
        _para1=@"para2";
        NSLog(@"excutebefore para1:%@,%p,%p",_para1,&_para1,_para1);
        myBlock(1);
        //block执行后
        NSLog(@"excuteafter para1:%@,%p,%p",_para1,&_para1,_para1);
    }

    输出:

    2014-07-28 17:05:47.701 Test[2307:60b] init para1:para1,0x39bb0,0x399e4
    2014-07-28 17:05:47.704 Test[2307:60b] excutebefore para1:para2,0x39bb0,0x39a24
    2014-07-28 17:05:47.705 Test[2307:60b] excuteing para1:para3,0x39bb0,0x39a04
    2014-07-28 17:05:47.706 Test[2307:60b] excuteafter para1:para3,0x39bb0,0x39a04

    从日志可以看出,block里变量地址和外部的是一样的,而且可以修改静态变量。

    我们看一下转换后的代码:

    static NSString * _para1;
    
    struct __KDBlockTest__test4_block_impl_0 {
      struct __block_impl impl;
      struct __KDBlockTest__test4_block_desc_0* Desc;
      __KDBlockTest__test4_block_impl_0(void *fp, struct __KDBlockTest__test4_block_desc_0 *desc, int flags=0) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };

    因为静态对象存在静态区(全局区)从创建到程序销毁一直存在,block内部没有声明对应的成员。下面是我们的test4 函数:

    static void _I_KDBlockTest_test4(KDBlockTest * self, SEL _cmd) {
        _para1=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_1;
    
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_2,_para1,&_para1,_para1);
        void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test4_block_impl_0((void *)__KDBlockTest__test4_block_func_0, &__KDBlockTest__test4_block_desc_0_DATA);
    
        _para1=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_5;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_6,_para1,&_para1,_para1);
        ((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1);
    
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_7,_para1,&_para1,_para1);
    }

    block初始化,传入实现函数的指针和描述函数,并没有其他参数。

    void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test4_block_impl_0((void *)__KDBlockTest__test4_block_func_0, &__KDBlockTest__test4_block_desc_0_DATA);

    我们来看下实现的函数,直接引用了静态变量

    static void __KDBlockTest__test4_block_func_0(struct __KDBlockTest__test4_block_impl_0 *__cself, int num) {
    
    
            _para1=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_3;
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_3979e1_mi_4,_para1,&_para1,_para1);
        }

    不考虑循环引用的基础上,静态变量和成员变量使用上方法大致一样,但是原理上还是有区别的。

    转载于:https://www.cnblogs.com/NarutoYq/p/3873686.html

    展开全文
  • Objective-C语法之代码块(block)的使用

    万次阅读 多人点赞 2012-09-25 11:22:19
    代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义...

    代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。

    脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义的返回值以及块的主体(也就是可以执行的代码)。下图是如何把块变量赋值给一个变量的语法讲解:


    按照调用函数的方式调用块对象变量就可以了:
    int result = myBlock(4); // result是 28

    1、参数是NSString*的代码块

            void (^printBlock)(NSString *x);
            printBlock = ^(NSString* str)
            {
                NSLog(@"print:%@", str);
            };
            printBlock(@"hello world!");
    运行结果是:print:hello world!

    2、代码用在字符串数组排序

            NSArray *stringArray = [NSArray arrayWithObjects:@"abc 1", @"abc 21", @"abc 12",@"abc 13",@"abc 05",nil];
            NSComparator sortBlock = ^(id string1, id string2)
            {
                return [string1 compare:string2];
            };
            NSArray *sortArray = [stringArray sortedArrayUsingComparator:sortBlock];
            NSLog(@"sortArray:%@", sortArray);
    
    运行结果:sortArray:(

        "abc 05",

        "abc 1",

        "abc 12",

        "abc 13",

        "abc 21"

    )

    3、代码块的递归调用

    代码块想要递归调用,代码块变量必须是全局变量或者是静态变量,这样在程序启动的时候代码块变量就初始化了,可以递归调用

            static void (^ const blocks)(int) = ^(int i)
            {
                if (i > 0) {
                    NSLog(@"num:%d", i);
                    blocks(i - 1);
                }
            };
            blocks(3);
    运行打印结果:

    num:3

    num:2

    num:1

     4、在代码块中使用局部变量和全局变量

    在代码块中可以使用和改变全局变量

    int global = 1000;
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            void(^block)(void) = ^(void)
            {
                global++;
                NSLog(@"global:%d", global);
            };
            block();
            NSLog(@"global:%d", global);
        }
        return 0;
    }

    运行打印结果:

    global:1001

    global:1001

    而局部变量可以使用,但是不能改变。

            int local = 500;
            void(^block)(void) = ^(void)
            {
    //            local++;
                NSLog(@"local:%d", local);
            };
            block();
            NSLog(@"local:%d", local);
    在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block

            __block int local = 500;
            void(^block)(void) = ^(void)
            {
                local++;
                NSLog(@"local:%d", local);
            };
            block();
            NSLog(@"local:%d", local);
    运行结果:local:501

                        local:501

    著作权声明:本文由http://blog.csdn.net/totogo2010/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!




    展开全文
  • 【小程序】block标签的介绍和使用

    万次阅读 2018-05-26 15:31:23
    block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 &lt...
    转自:https://blog.csdn.net/qq_36530458/article/details/79778373
    1. <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
    2. 因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
            <block wx:if="{{true}}">
                 <view> view1 </view>
                <view> view2 </view>
            </block>
    1. 类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:
        <block wx:for="{{[1, 2, 3]}}">
        <view> {{index}}: </view>
         <view> {{item}} </view>

    </block>


    在安卓中我们经常会使用ListView/GridView/RecyclerView来实现展示循环数据。那么小程序中怎么到呢。其实很简单,使用block就可以了。

    下面我们先看下效果图:

    这个布局其实很简单,大致分为3部分,上+下(左75%,右25%)。这里就不在细说了。那么这里要怎么写wxml呢。下面贴代码:

    这边很清晰的可以看出<block></block>这对标签,而数据源便是wx:for="{{goodlist}}"中的goodlist了。接着往下走,我们可以看到点击标签的时候有bindtap事件,这里就不做说明了。我们重点看下{{item.StartCity}},这是什么意思呢,其实这就是获取数据源中的数据,而item代表的是goodlist中的一条数据,StrrtCity等都是数据源中的一些具体属性。你可以更据需要直接调头你想要的字段名就可以了。block到此基本结束了。最后此处设置了一个view,用来代替当数据源为空时显示无数据页面提示。


    展开全文
  • 前言循环引用: *对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象: *对于ARC下 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong...
  • 本系列博文总结自《Pro Multithreading and Memory Management for iOS and OS X with ARC》 如果您觉得我的博客对您有帮助,请通过关注我的新浪微博 ...本文将介绍可写变量、block的内存段、__block变量的内存段等
  • block(程序块)

    千次阅读 2013-07-19 11:55:54
    之前程序中一直用block这里把它进行归类一下。block是ios4.0之后出来的一门新技术,应用也非常广泛,只要我们撑握其使用的翘门,使 用其来也是非常简单的,而且它能将传统程序简单化  程序中" ^ "代表程序块也就是...
  • 面试题block的原理是怎样的?本质是什么?__block的作用是什么?有什么使用注意点?block的属性修饰词为什么是copy?使用block有哪些使用注意?block在修改NSMutableArray,需不需要添加__block?首先对block有一个...
  • Block讲解

    2018-07-20 02:21:24
    // // StudyBlock.m // PodProduct // // Created by wzk on 2018/3/7. // Copyright © 2018年 wzk....// #import "StudyBlock.h"...//---------------------单例的写法 ... 作用:对于某...
  • C++ Block(代码块)

    千次阅读 2016-07-27 16:40:09
    Block是什么?Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象;它也很像C++中的函数对象,因为除了要执行的代码,block还可以携带和...
  • Simple File System

    2019-01-04 13:12:28
    This is my operating system class design. 1.一段代码及其bug. class Program { static void Main(string[] args) { string file = "weidiao"; if (File.Exis...
  • 理解Linux文件系统之 inode

    千次阅读 2018-06-26 22:47:52
    操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是4KB,...
  • 一.inode size 定义inode table是data area的索引表. Inode分内存中的inode和文件系统中的inode...inode table上有许多的inode, 每个inode分别记录一个档案的属性与这个档案分布在哪些datablock上(也就是我们说...
  • iOS进阶面试题----Block部分

    万次阅读 2016-03-21 15:30:49
    1 什么是block 对于闭包(block),有很多定义,其中闭包就是能够读取其它函数内部变量的函数,这个定义即接近本质又较好理解。对于刚接触Block的同学,会觉得有些绕,因为我们习惯写这样的程序main(){ funA();} funA...
  • IndentationError: expected an indented block解决方案

    万次阅读 多人点赞 2018-07-15 12:14:07
    IndentationError: expected an indented block 翻译过来就是: 缩进错误: 期望一个缩进的块 贴下报错的代码的截图便于观察分析: 好了,直接开始单刀直入解决这个问题,解决方案,在报错的逻辑代码的前面加个...
  • ----------------------------------------欢迎查看block连载博客:【专栏】---------------------------------------【block编程第一篇】block语法 【block编程第二篇】block捕获变量和对象(当前)【block编程第三...
  • block、inline、inline-block的区别

    千次阅读 2019-01-15 21:14:58
    一、display:block特点 1、独占一行,多个block元素另起一行,默认情况下,block元素宽度自动填满其父元素宽度 2、block元素可以设置width,height属性。块元素即使设置了宽度,仍然是独占一行。 3、block元素可以设置...
  • 正如它们名字说的那样,说明了block的三种存储方式:栈、全局、堆。 【在ARC下】:似乎已经没有栈上的block了,要么是全局的,要么是堆上的。有一个特殊情况:如果仅仅定义了block没有赋值给变量的话,仍是在栈上,...
  • 小程序中的block

    万次阅读 2017-12-20 15:47:44
    并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。因为 wx:if 是一个控制属性,需要将它添加到一个标签上。... block wx:if="{{true}}">  view> view1 view>  
  • 写给喜欢用Block的朋友(ios Block)

    万次阅读 多人点赞 2014-07-24 19:58:43
    IOS block 中使用注意的问题 1.block 的循环引用(retain cycle) 2.去除block产生的告警时,需注意问题。
1 2 3 4 5 ... 20
收藏数 1,202,715
精华内容 481,086
关键字:

block