按值或引用访问变量

时间:2011-06-21 23:50:43

标签: objective-c objective-c-blocks

在下面的示例中,我不明白为什么localVariabledoSomethingWithObject中的值访问self。是什么促成了转换?您如何区分按值访问变量和通过引用访问变量?如果可能的话,我希望看到更多相关的例子。

以下是Apple Blocks Programming Topics的摘录,并显示了如何在块中保留实例变量。

  

如果你在里面使用一个块   执行方法,规则   用于对象的内存管理   实例变量更加微妙:

     
      
  • 如果您通过引用访问实例变量,则会保留dispatch_async(queue, ^{ // instanceVariable is used by reference, self is retained doSomethingWithObject(instanceVariable); }); id localVariable = instanceVariable; dispatch_async(queue, ^{ // localVariable is used by value, localVariable is retained (not self) doSomethingWithObject(localVariable); }); ;
  •   
  • 如果按值访问实例变量,则保留变量。
  •   
     

以下示例说明了   两种不同的情况:

{{1}}

1 个答案:

答案 0 :(得分:12)

这是因为当您直接访问实例变量时,编译器(或多或少)会将其转换为结构成员查找。所以:

[ivar doSomething];

变为

[self->ivar doSomething];

由于需要self,因此必须保留self。但是,当您将指针值复制到新变量中时,您知道更长时间需要self结构来知道指针值是什么,因此self不需要保留,因为指针值可以从堆栈中复制const。实例变量不会发生这种情况(因为在创建块和执行块时,ivar可能会发生变化)。


澄清:

  • 一个块必须保留它在内部引用的所有对象,以确保这些对象在块的生命周期内继续存在。
  • 当您直接在代码中访问ivar时,您实际上只是查找结构的成员(因为Objective-C对象实际上只是结构)
  • 查找结构的成员意味着您必须拥有结构
  • 因此,一个块将保留结构(在本例中为self),以便查找始终成功。如果它没有这样做,那么将来可能会释放self,现在结构查找会导致访问不良(最有可能)并且您的应用程序会崩溃。
  • 或者,您可以在当前堆栈帧中本地创建新的对象指针。这样做的好处是您不再需要保留self,因为self不再涉及检索相关对象的地址
  • 当然,将保留局部变量引用的对象,以确保它在块的生命周期内存在。
  • 使用术语“按值”和“按引用”这里完全不正确。 Objective-C中的对象总是通过引用传递,因为我们总是传递指针。您无法在Objective-C中按值传递对象。 (对此有一些警告,但你真的不想去那里)有关通过-val值与by-reference传递内容意味着什么的更多信息,请查看以下问题:{ {3}}