【问题标题】:What is the reason that a compiler would not treat every variable as a __block variable?编译器不会将每个变量都视为 __block 变量的原因是什么?
【发布时间】:2011-10-31 02:49:23
【问题描述】:

编译器(特别是 Xcode 使用的编译器)不将每个变量都视为 __block 变量的性能提升是什么?我想一定有什么,我怀疑在 __block 变量的概念中,它决定了

 __block SelfClass * blockSelf = self;

语法很好,很方便。

【问题讨论】:

    标签: objective-c xcode objective-c-blocks clang


    【解决方案1】:

    块的目标是尽可能自动化和透明地使用语法最少的块并让它们“正常工作”。

    默认情况下,非__block 变量更符合块所代表的“闭包”概念。在执行通过块声明时,块会快照块内引用的所有变量的状态。这包括复制内存/状态和保留块中捕获的任何 Objective-C 对象引用。

    __block 有效地破坏了块内状态的封装。非常有用,但需要程序员手动管理对象引用。

    即非 __block 变量“正常工作”更多的是 __block 变量,因此,默认行为是倾向于“正常工作”。

    实际上,在块中捕获状态的成本通常是最低的。对应用性能的可衡量影响通常很少见,而且通常表明存在更深刻的架构问题。


    如果通过:

     __block SelfClass * blockSelf = self;
    

    您指的是 Blocks 和 ARC 的交叉产品吗?是的,这有点不幸。但是编译器也会警告您需要注意的一个非常现实的问题。但是,更简洁的解决方法显然更可取。

    【讨论】:

      【解决方案2】:

      因为__block 可能会在堆栈破坏中幸存下来。这只有在使用 c++ 范围变量时才会注意到:

      {
          __block shared_ptr<A> ptr = make_shared(new A);
          self.some_block = ^(void){};
      } // ptr will not be deleted until the block is destructed
      {
         shared_ptr<A> ptr = make_shared(new A);
          self.some_block = ^(void){};
      } // ptr will be deleted here
      

      垃圾收集也很明显,但它不太明显且难以举例。

      【讨论】:

      • 不完全;在这两种情况下,块都是堆栈范围的块,因此将随着范围被破坏。您必须复制该块以使其在范围内存活。同样,这只是__block 的一个小细节;还有许多其他驱动因素。
      猜你喜欢
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 2021-04-14
      • 1970-01-01
      • 2013-06-16
      相关资源
      最近更新 更多