我知道如果复制了访问它的Block,__block
变量将从堆栈移到堆中。但是下面的测试代码告诉我,{<1}}变量在块复制之前被移动到堆。
也就是说,四个输出是:stack =&gt; heap =&gt; heap =&gt;堆,这不是我期望的结果:stack =&gt; stack =&gt; stack =&gt;堆。
有人能把我拉直吗?
__block
答案 0 :(得分:3)
让我先说一下:块很奇怪。
现在,当你开始时,你已经声明了一个变量x,并且还用__block
作为前缀。无论如何,__block
到底是什么?好吧,对于在块的词法范围内捕获的对象,变量是-retain
',以便保证它们在执行块时出现。但是对于原始变量,块通过强制它们通过const
值而不是通过引用来保护它们的值。通过预先__block
,您可以让编译器自由执行命令,以便在复制块时将您的变量“神奇地”从堆栈移动到堆中。为了清楚起见,__block
变量实际上是堆栈分配的,但是在复制块时它们会被移动到堆(malloc()
'd)。
但是x的位置有什么奇怪的变化呢?好吧,再回到__block
。因为你没有像正常变量那样使用const
对x的引用,所以块使用(稍微讨厌)技巧:块创建指向任何__block
变量的指针,如果该变量发生变异,它被解除引用。塔达!你的变量没有从堆栈移动到堆,块只是取消引用它的指针并将其移动到内存中!
所以,实际上,您对变量移动的位置和时间感到困惑。您的示例是记录正确的值。
答案 1 :(得分:2)
您的预期输出是基于您在步骤3-4之前不会复制块的假设。但是,块规范中的任何内容都不能保证这种情况。
是的,当您在其上明确地呼叫-copy
时,将立即复制该块。但为什么不能早点复制呢?先前复制块永远不会错误。因此,当确切地复制一个块是未定义的时,你不应该依赖它。
ARC下的一些最新版本的编译器可能是保守的,并在创建后立即复制一个块。没有什么不妥。同样,如果它这样做,它将是一个实现细节,其他编译器或未来版本可能会做一些不同的事情。
答案 2 :(得分:0)
我在In Objective-C with ARC, what does compiler do when I define a block?
问了同样的问题您在ARC中运行代码的情况
在ARC,
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#blocks 中的可保留对象所有者类型的块变量被移出 堆栈通过初始化堆副本与从中移动的结果 堆栈副本。