为什么在复制块之前将__block变量移动到堆中? [英] Why is a __block variable is moved to the heap BEFORE the block is copied?

查看:106
本文介绍了为什么在复制块之前将__block变量移动到堆中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如果复制了访问它的Block,那么 __ block 变量将从堆栈移到堆中。但是下面的测试代码告诉我,在块复制之前, __ block 变量被移动到堆

I know that a __block variable will be moved to the heap from the stack if a Block accessing it was copied. But the following test code show me that the __block variable is moved to the heap before the Block's copying.

也就是说,四个输出是:stack => heap => heap => heap,这不是我期望的结果:stack => stack => stack => heap。

That is, the four outputs are: stack => heap => heap => heap, which is not my expected result: stack => stack => stack => heap.

有人能把我拉直吗?

__block int x = 0;
int *pointerToX = &x;
//1. It's on the stack
NSLog(@"x's location is on the stack: %p", &x);
int (^block)() = ^{
    x += 1;
    return x;
};

//2. I think its stack, but it's heap
NSLog(@"x's location is on the %@: %p", (&x == pointerToX ? @"stack" : @"heap"), &x); //it's heap not stack

block();
//3. I think its stack, but it's heap
NSLog(@"x's location is on the %@: %p", (&x == pointerToX ? @"stack" : @"heap"), &x); //it's heap not stack

block = [block copy]; // The variable x will be moved to the heap
//4. I think its stack, but it's heap
NSLog(@"x's location is on the %@: %p", (&x == pointerToX ? @"stack" : @"heap"), &x); //heap


推荐答案

让我先说一下:块很奇怪。

Let me preface this by saying: Blocks are weird.

现在,当你开始时,你已经声明了一个变量x,并且还用 __ block 。到底是什么 __ block 无论如何?好吧,对于在块的词法范围内捕获的对象,变量是 -retain 'ed,以便保证它们在执行块时出现。但是对于原始变量,块通过强制它们通过 const 值而不是通过引用来传递它们来保护它们的值。通过预先添加 __ block ,您可以让编译器自由执行命令,以便在复制块时将您的变量神奇地从堆栈移动到堆中。要清楚, __ block 变量实际上是堆栈分配的,但它们被移动到堆中( malloc()'d)复制块时。

Now, when you start out, you've declared a variable x, and also prefixed it with __block. What the heck is __block anyhow? Well, for objects captured in the lexical scope of the block, variables are -retain'ed so as to guarantee they are around when the block is executed. But for primitive variables, blocks secure their values by forcing them to be passed by const value rather than by reference. By prepending __block, you've given the compiler free reign to move your variable "magically" from the stack to the heap when the block is copied. To be clear, __block variables are, in fact, stack allocated, but they are moved to the heap (malloc()'d) when the block is copied.

但是x的位置有什么奇怪的变化呢?好吧,再次回到 __ block 。因为你没有像正常变量那样使用 const 对x的引用,所以块使用(稍微讨厌)技巧:一个块创建指向任何 __ block 变量,如果该变量发生变异,则将其解除引用。塔达!你的变量没有从堆栈移动到堆,块只是取消引用它的指针并将其移动到内存中!

But what about the weird changes in the location of x? Well, back to __block again. Because you're not using a const reference to x like a normal variable, blocks use a (slightly annoying) trick: A block creates a pointer to any __block variable, and if that variable is mutated, it is dereferenced. Ta da! Your variable didn't move from the stack to the heap, the block merely dereferenced the pointer to it and moved it in memory!

所以,实际上,您对变量移动的位置和时间感到困惑。您的示例是记录正确的值。

So, really, you're confused about where and when your variables are moved around. Your example is logging the correct values.

这篇关于为什么在复制块之前将__block变量移动到堆中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆