The profound meaning of adding __block to block

Block does not allow to modify the value of external variables. The value of external variables mentioned here refers to the memory address of the pointer in the stack. The function of __block is to put the memory address of the "external variable" on the stack into the heap as long as the variable is observed to be held by the block. Furthermore, the value of external variables can also be modified inside the block. ---This is the description in Section 11.2.3 of "Advanced iOS Development" by Weibo @tangqiao_boy.

Simple data type local variables

plus __block case
  1. Here a is a local variable, so it is placed on the stack. block is equivalent to another internal function, it is not acceptable to change the memory address of the pointer on the stack in another scope. At this point, if the block wants to operate internally, the a variable must be copied to the heap, and the program can change it.
  2. Print the address of a again in the block, and you can find that the address is different. This is the role of __block, which copies the variable a in the stack and puts it on the heap. (The output is the heap address at this time)
  3. 0x7 is the address on the stack. The addresses starting with 0x1 are on the heap.
  4. After calling block, the a variable is already a new memory address and is no longer on the stack.
  5. If __block is not added here, a = 3 is to modify the memory address of the a pointer. This is not acceptable.

Immutable object local variables

NSString object
  1. NSString is an immutable string, and the content cannot be modified after initialization (the content here refers to the content of the space opened up on the heap). Without __block, the string pointer reference will always be the content address at initialization (that is, always point to @"dddd").
  2. After adding __block, the string will be copied from the stack to the heap inside the block. In this way, we can manipulate the pointer memory address of the string and modify it. That is, the operation that can string = @"fffff".
  3. It can be seen that after the block, all the strings are copied to the heap. (Special note: When an object is generated, a pointer address will be opened on the stack, and a heap address will be stored in the pointer address. This address is the area where the content of the object is actually stored. That is to say, objects are placed on the heap.)

mutable object local variables

<p>(1) Add __block case</p>

<pre><code>
` int b = 1;
__block NSMutableString *a = [NSMutableString stringWithString:@"Tom"];
NSLog(@"start%@",a);
NSLog(@"b's address is the start of the stack address %p",&b);
NSLog(@"\nBefore setting: ---------------------------------- --\n
The heap address pointed to by a: %p; the pointer address of a in the stack: %p", a, &a); //a is in the stack area
void (^foo)(void) = ^{

        a.string = @"Jerry";
        NSLog(@"\n block内部:------------------------------------\n\
              a指向的堆中地址:%p;a在栈中的指针地址:%p", a, &a);               //a在栈区
        a = [NSMutableString stringWithString:@"William"];
        
        NSLog(@"block内部%@",a);
    };
    foo();
    NSLog(@"\n 定以后:------------------------------------\n\
          a指向的堆中地址:%p;a在栈中的指针地址:%p", a, &a);               //a在栈区
    
    NSLog(@"最后%@",a);`

</code>
</pre>


Add __block case output result
  1. It can be found that after block, all the contents of a are copied to the heap.
  2. a = [NSMutableString stringWithString:@"William"]; is to change the content of the a pointer address.

<p>(2) The case of not adding __block</p>

<pre><code>
` int b = 1;
NSMutableString *a = [NSMutableString stringWithString:@"Tom"];
NSLog(@"start%@",a);
NSLog(@"b's address is the start of the stack address% p",&b);
NSLog(@"\nBefore setting: ----------------------------------- -\n
The heap address pointed to by a: %p; the pointer address of a in the stack: %p", a, &a); //a is in the stack area
void (^foo)(void) = ^{

        a.string = @"Jerry";
        NSLog(@"\n block内部:------------------------------------\n\
              a指向的堆中地址:%p;a在栈中的指针地址:%p", a, &a);               //a在栈区
      //  a = [NSMutableString stringWithString:@"William"];
        
        NSLog(@"block内部%@",a);
    };
    foo();
    NSLog(@"\n 定以后:------------------------------------\n\
          a指向的堆中地址:%p;a在栈中的指针地址:%p", a, &a);               //a在栈区
    
    NSLog(@"最后%@",a);`

</code>
</pre>

Output result without adding __block
  1. Mutable objects can directly modify the content without adding __block.
  2. a.string = @"Jerry" modifies the contents of the heap. Not the pointer address of a on the stack.
  3. So in the end, the address of a on the heap and the address of a on the stack have not changed. All that changes is what a is pointing to at the address on the heap.


Author: Brother i Big Cat
Link : https://www.jianshu.com/p/a41396ff0247
Source: Jianshu The
copyright belongs to the author. For commercial reprints, please contact the author for authorization, and for non-commercial reprints, please indicate the source.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326803745&siteId=291194637