为什么一个__block变量移到堆前的块复制? [关闭](Why is a __block va

2019-07-20 13:19发布

我知道一个__block变量从栈如果一个块访问它被复制移到堆。 但是,下面的测试代码,告诉我该__block变量块的复制移到堆。

也就是说,四个输出分别是:堆栈=>堆=>堆=>堆,这是我的不期望的结果:堆栈=>堆=>堆=>堆。

可能有人理顺我吗?

__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

Answer 1:

最后,我要说前言本:块是怪异。

现在,当你开始,你声明一个变量x,并与前缀它__block 。 到底是什么__block无论如何? 那么,对于在块的词汇范围,拍摄的对象,变量是-retain “版,以保证程序被执行时,他们周围。 但对于原始变量,块,迫使他们通过传递保护他们的价值观const的值而不是引用。 通过预先__block ,你给编译器自由支配当块复制到从栈中移动你的变量“神奇”来堆。 为了清楚起见, __block变量,事实上,堆栈中分配,但是它们被移动到堆( malloc() “d)当块被复制。

但是,我们在X的位置怪异的变化? 好了,回到__block一次。 因为你没有使用const引用像一个正常的变量x,模块使用(有点烦)绝招:一个块创建一个指向任何__block变量,如果该变量突变,它被解除引用。 ただ! 您的变量并没有从堆栈堆移动,块只是取消引用的指针,并在内存中移动它!

所以,真的,你困惑在哪里,当你的变量左右移动。 您的例子是登录正确的值。



Answer 2:

你期望的输出是基于你的假设块不被复制,直到步骤3-4。 然而,没有在块规格保证这将是这种情况。

是的,该块将在最新的被复制,当您显式调用-copy就可以了。 但是,为什么不能早些复制? 这是从来没有更早复制块。 因此,当整整块复制是不确定的,你不应该依赖于它。

最近的一些ARC下的编译器的版本可能是保守的,并在创建后立即复制块。 没有什么不妥。 同样,如果它这样做,这将是一个实现细节,以及其他编译器或未来版本可能会做不同的事情。



Answer 3:

我问了同样的问题在在Objective-C与ARC,这是什么做的编译器,当我定义一个块?

如果你运行在ARC的代码

在ARC,

可保持对象所有者类型的块变量通过用从栈拷贝移动的结果初始化堆拷贝移动离开堆栈。

在http://clang.llvm.org/docs/AutomaticReferenceCounting.html#blocks



文章来源: Why is a __block variable is moved to the heap BEFORE the block is copied? [closed]