• Blocks and Variables


    This article describes the interaction between blocks and variables, including memory management.

    Types of Variable

    Within the block object’s body of code, variables may be treated in five different ways.

    You can reference three standard types of variable, just as you would from a function:

    • Global variables, including static locals

    • Global functions (which aren’t technically variables)

    • Local variables and parameters from an enclosing scope

    Blocks also support two other types of variable:

    1. At function level are __block variables. These are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap.

    2. const imports.

    Finally, within a method implementation, blocks may reference Objective-C instance variables—see Object and Block Variables.

    The following rules apply to variables used within a block:

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

    2. Parameters passed to the block are accessible (just like parameters to a function). 

    3. Stack (non-static) variables local to the enclosing lexical scope are captured as const variables.

      Their values are taken at the point of the block expression within the program. In nested blocks, the value is captured from the nearest enclosing scope. 

    4. Variables local to the enclosing lexical scope declared with the __block storage modifier are provided by reference and so are mutable.

      Any changes are reflected in the enclosing lexical scope, including any other blocks defined within the same enclosing lexical scope. These are discussed in more detail in The __block Storage Type

    5. Local variables declared within the lexical scope of the block, which behave exactly like local variables in a function. 

      Each invocation of the block provides a new copy of that variable. These variables can in turn be used as const or by-reference variables in blocks enclosed within the block. 

    The following example illustrates the use of local non-static variables:

    int x = 123;
     
    void (^printXAndY)(int) = ^(int y) {
     
        printf("%d %d
    ", x, y);
    };
     
    printXAndY(456); // prints: 123 456

    As noted, trying to assign a new value to x within the block would result in an error:

    int x = 123;
     
    void (^printXAndY)(int) = ^(int y) {
     
        x = x + y; // error
        printf("%d %d
    ", x, y);
    };

    To allow a variable to be changed within a block, you use the __block storage type modifier—see The __block Storage Type.

    The __block Storage Type

    You can specify that an imported variable be mutable—that is, read-write— by applying the __block storage type modifier. __block storage is similar to, but mutually exclusive of, the registerauto, and static storage types for local variables. 

    __block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.

    As an optimization, block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy), variables are copied to the heap. Thus, the address of a __block variable can change over time.

    There are two further restrictions on __block variables: they cannot be variable length arrays, and cannot be structures that contain C99 variable-length arrays. 

    The following example illustrates use of a __block variable: 

    __block int x = 123; //  x lives in block storage
     
    void (^printXAndY)(int) = ^(int y) {
     
        x = x + y;
        printf("%d %d
    ", x, y);
    };
    printXAndY(456); // prints: 579 456
    // x is now 579

    The following example shows the interaction of blocks with several types of variables:

    extern NSInteger CounterGlobal;
    static NSInteger CounterStatic;
     
    {
        NSInteger localCounter = 42;
        __block char localCharacter;
     
        void (^aBlock)(void) = ^(void) {
            ++CounterGlobal;
            ++CounterStatic;
            CounterGlobal = localCounter; // localCounter fixed at block creation
            localCharacter = 'a'; // sets localCharacter in enclosing scope
        };
     
        ++localCounter; // unseen by the block
        localCharacter = 'b';
     
        aBlock(); // execute the block
        // localCharacter now 'a'
    }

  • 相关阅读:
    计算机网络概述---传输层 UDP和TCP
    计算机网络概述---网络层
    计算机网络概述---数据链路层
    计算机网络概述---物理层
    计算机网络概述---OSI参考模型
    Java 集合系列18之 面试题
    【Vue-01】基础Vue语法+JS复习
    SpringBoot 注册Servlet三大组件【Servlet、Filter、Listener】-原生代码+@Bean+效果展示
    Springboot的 get查看,post创建,put更新,delete删除 -四种请求实例(form + controller)
    【Bug档案01】Spring Boot的控制器+thymeleaf模板 -使用中出现静态资源加载路径不当的问题 -解决时间:3h
  • 原文地址:https://www.cnblogs.com/feng9exe/p/7485259.html
Copyright © 2020-2023  润新知