So after the call local refers to the new object, and it has 2 owners - local accounts for one, and the other is the autorelease in indirect:ark[2041:707] >>> 0x100427d10: release demo1现在已完成,因此ARC在localdemo1 is now finished so ARC releases the object in localark[2041:707] Flush demo1ark[2041:707] >>> 0x100427d10: releaseark[2041:707] >>> 0x100427d10: deallocark[2041:707] End demo1,并且demo1返回本地化的@autoreleasepool后,会处理indirect:的自动释放,现在所有权为零,我们得到了dealloc.and after demo1 returns the localized @autoreleasepool handles the autorelease pending from indirect:, now the ownership is zero and we get the dealloc. 通过引用传递实例变量以上内容处理了通过引用传递局部变量的问题,但不幸的是,传写回传不能用于实例变量.有两种基本解决方案:The above deals with passing local variables by reference, but unfortunately pass-by-writeback does not work for instance variables. There are two basic solutions: 将实例变量复制到本地copy your instance variable to a local添加一些属性为了演示第二个示例,我们在类ByRef中添加了strongIndirect:,该类指定它需要引用强变量:To demonstrate the second we add to class ByRef a strongIndirect: which specifies it requires a reference to a strong variable:- (void) strongIndirect:(Breadcrumbs * __strong *)byRef{ *byRef = [Breadcrumbs newWith:@"plum"];}- (void) strongIndirectWrapper:(Breadcrumbs * __strong *)byRef{ NSLog(@"strongIndirect: passed reference %p, contains %p - %@, owners %lu", byRef, *byRef, *byRef, [*byRef ownerCount]); [self strongIndirect:byRef]; NSLog(@"strongIndirect: returned");}和相应的demo2,它使用ByRef的实例变量(再次使用instance的虚构名称):and a corresponding demo2 which uses ByRef's instance variable (again with the imaginative name of instance):- (void) demo2{ NSLog(@"Strong instance passed by strong reference"); instance = [Breadcrumbs newWith:@"orange"]; NSLog(@"instance: addr %p, contains %p - %@, owners %lu", &instance, instance, instance, [instance ownerCount]); [self strongIndirectWrapper:&instance]; NSLog(@"instance: addr %p, contains %p - %@, owners %lu", &instance, instance, instance, [instance ownerCount]);}使用与上述demo1类似的代码执行此操作,我们得到:Execute this with a similiar piece of code as for demo1 above and we get:1 ark[2041:707] Start demo22 ark[2041:707] Strong instance passed by strong reference3 ark[2041:707] >>> 0x100176f30: init4 ark[2041:707] instance: addr 0x100147518, contains 0x100176f30 - orange, owners 15 ark[2041:707] strongIndirect: passed reference 0x100147518, contains 0x100176f30 - orange, owners 16 ark[2041:707] >>> 0x100427d10: init7 ark[2041:707] >>> 0x100176f30: release8 ark[2041:707] >>> 0x100176f30: dealloc9 ark[2041:707] strongIndirect: returned10 ark[2041:707] instance: addr 0x100147518, contains 0x100427d10 - plum, owners 111 ark[2041:707] Flush demo212 ark[2041:707] End demo2哪个比以前短一些.这有两个原因:Which is a bit shorter than before. This is for two reasons: 当我们将强变量(instance)传递给方法(strongIndirect:)时,该方法期望引用强变量,因此ARC无需使用隐藏变量-行中的变量上面的4和5相同(0x100147518).As we are passing a strong variable (instance) to a method (strongIndirect:) which expects a reference to a strong variable there is no need for ARC to use a hidden variable - the variables in line 4 and 5 above are the same (0x100147518).由于ARC知道strongIndirect:中的引用变量很强,因此无需在strongIndirect:中存储自动释放的引用,然后在调用后写回该值-ARC只是执行标准的强分配,第6行-8,以后没有自动释放的内容(在第11和12行之间).As ARC knows the referenced variable in strongIndirect: is strong there is no need to store an autoreleased reference within strongIndirect: and then write this back after the call - ARC just does a standard strong assignment, lines 6-8, and there is nothing to autorelease later (between lines 11 and 12). strongIndirect:是否适用于强大的本地人?Does strongIndirect: work for strong locals?当然,这是demo3:- (void) demo3{ NSLog(@"Strong local passed by strong reference"); Breadcrumbs *local; // __strong inferred local = [Breadcrumbs newWith:@"apple"]; NSLog(@"local: addr %p, contains %p - %@, owners %lu", &local, local, local, [local ownerCount]); [self strongIndirectWrapper:&local]; NSLog(@"local: addr %p, contains %p - %@, owners %lu", &local, local, local, [local ownerCount]);}使用我们的标准包装器执行此操作会产生:Executing this with our standard wrapper produces:1 ark[2041:707] Start demo32 ark[2041:707] Strong local passed by strong reference3 ark[2041:707] >>> 0x100176f30: init4 ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 15 ark[2041:707] strongIndirect: passed reference 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 16 ark[2041:707] >>> 0x100427d20: init7 ark[2041:707] >>> 0x100176f30: release8 ark[2041:707] >>> 0x100176f30: dealloc9 ark[2041:707] strongIndirect: returned10 ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100427d20 - plum, owners 111 ark[2041:707] >>> 0x100427d20: release12 ark[2041:707] >>> 0x100427d20: dealloc13 ark[2041:707] Flush demo314 ark[2041:707] End demo3这与前面的示例几乎相同,只有两个小的区别:This is almost the same as the previous example, just two minor differences: 通过堆栈上的本地地址(0x7fff5fbfedc0),第4行和第5行当它存储在本地时,新对象将由ARC第11和12行清除As it is stored in a local the new object is cleaned up by ARC, lines 11 and 12 为什么不总是将__strong添加到引用参数?Why not always add __strong to reference arguments?一个原因是因为并非所有事物都强大! ARC的传递回写功能也适用于弱势本地用户.我们的最终演示:One reason is because not everything is strong! ARC's pass-by-writeback works for weak locals as well. Our final demo:- (void) demo4{ NSLog(@"Weak local passed by autoreleasing reference"); instance = [Breadcrumbs newWith:@"peach"]; Breadcrumbs __weak *weakLocal = instance; NSLog(@"weakLocal: addr %p, contains %p - %@, owners %lu", &weakLocal, weakLocal, weakLocal, [weakLocal ownerCount]); [self indirectWrapper:&weakLocal]; NSLog(@"weakLocal: addr %p, contains %p -, %@, owners %lu", &weakLocal, weakLocal, weakLocal, [weakLocal ownerCount]);} [这里我们只使用了instance,因此我们需要对其进行弱引用."[Here we've just used instance so we have something to make a weak reference to.]使用我们的标准包装器执行此操作会产生:Executing this with our standard wrapper produces: 1 ark[2041:707] Start demo4 2 ark[2041:707] Weak local passed by autoreleasing reference 3 ark[2041:707] >>> 0x608000000d10: init 4 ark[2041:707] weakLocal: addr 0x7ffeefbfde58, contains 0x608000000d10 - peach, owners 4 5 ark[2041:707] >>> 0x608000000d10: retainWeakReference 6 ark[2041:707] indirect: passed reference 0x7ffeefbfde40, contains 0x608000000d10 - peach, owners 2 7 ark[2041:707] >>> 0x604000001060: init 8 ark[2041:707] >>> 0x604000001060: autorelease 9 ark[2041:707] indirect: returned10 ark[2041:707] >>> 0x608000000d10: release11 ark[2041:707] weakLocal: addr 0x7ffeefbfde58, contains 0x604000001060 - banana, owners 412 ark[2041:707] Flush demo413 ark[2041:707] >>> 0x604000001060: release14 ark[2041:707] >>> 0x604000001060: dealloc15 ark[2041:707] End demo416 ark[2041:707] >>> 0x608000000d10: release17 ark[2041:707] >>> 0x608000000d10: dealloc注意: 第3、16和9行17与instance有关-创建新值并发布&最后释放的内容-重要的内容从第4行开始Lines 3, 16 & 17 are related to instance - create a new value and release & deallocated at the end - the important stuff starts at line 4第4行显示了已分配给weakLocal的内容,请注意,将`instance'的强引用复制到此弱变量中不需要任何保留. (注意:显示弱变量的内容确实涉及一些保留和释放操作,为清楚起见已将其删除.)Line 4 shows what has been assigned to weakLocal, note that copying the strong reference from `instance into this weak variable does not require any retain. (Note: displaying the contents of a weak variable does involved some retain and release operations, these have been elided for clarity.) ARC对弱局部变量(第4行,0x7ffeefbfde58)也使用隐藏变量(第6行,0x7ffeefbfde40).在强本地情况(demo1)中,ARC知道存储在此隐藏变量中的引用将保持有效,并避免使用自动释放池.在这种情况下,这不能保证,但是ARC仍然设法避免使用自动释放池:ARC保留了引用(第5行,retainWeakReference是retain的特殊版本,用于弱变量),并且在调用完成后,可以使用发布(第10行).与使用自动释放池相比,这会缩短强引用的寿命.ARC uses a hidden variable (line 6, 0x7ffeefbfde40) for weak locals (line 4, 0x7ffeefbfde58) as well. In the strong local case (demo1) ARC knows the reference stored in this hidden variable will remain valid and avoids using the autorelease pool. In this case this isn't guaranteed but ARC still manages to avoid the autorelease pool: ARC retains the reference (line 5, retainWeakReference is a special version of retain for weak variables) and after the call has completed balances this with a release (line 10). This shortens the lifetime of the strong reference compared to using the autorelease pool. indirectWrapper(第8行)中的自动释放分配(0x604000001060)在排空池(第13和14行)时达到平衡.最后,当我们的ByRef实例消失时,ARC会清理存储在instance(0x608000000d10)中的对象.The autoreleased assignment (0x604000001060) inside indirectWrapper (line 8) is balanced when the pool is drained (lines 13 & 14). Finally ARC cleans up the object stored in instance (0x608000000d10) when our ByRef instance goes away. 摘要 没有任何添加的属性,ARC将对通过引用作为参数传递的局部(推断的强)变量(推断的自动释放)做正确的事情. (本地"包括当前方法的参数.)Without any added attributes ARC will do the right thing for local (inferred strong) variables passed as parameters by reference (inferred autoreleasing). (And "local" includes parameters to the current method.)这是由ARC使用传递回写的方式实现的,并且只有遵循"out"参数模式时,仅才有效.如果您希望存储传递的参考以供以后使用,则需要自己做更多的事情.This is implemented by ARC using pass-by-writeback and only works if you follow the "out" parameter pattern. If you wish to store the passed reference for use later you'll need to do more yourself.如果希望通过引用传递实例变量,则需要将其复制到本地变量中,或使用__strong赋予接收参数类型属性.If you wish to pass instance variables by reference you either need to copy them into locals or attribute the receiving parameter type with __strong.通过写回传递也适用于__weak当地人.pass-by-writeback also works for __weak locals.希望有帮助. 附录2016年4月:__block变量Addendum Apr 2016: __block variables在希思·边界的评论中,In the comments Heath Borders has asked:有趣的问题. 规范状态:•&var,其中var是具有可保留对象指针类型的自动存储持续时间的标量变量• &var, where var is a scalar variable of automatic storage duration with retainable object pointer type默认情况下(Objective-)C中的局部变量具有自动存储期限-在输入/退出其封闭函数/方法/块时,它们会自动创建和销毁.在上面的答案中,当我们提到局部变量"时,我们隐式地指的是具有自动存储持续时间的局部变量.Local variables in (Objective-)C by default have automatic storage duration - they are automatically created and destroyed as their enclosing function/method/block is entered/exited. In the above answer when we refer to "local variable" we are implicitly referring to local variables with automatic storage duration.可以使用存储限定符或存储类说明符声明局部变量,以更改变量的存储持续时间.最常见的是static;具有静态存储持续时间的局部变量在程序的整个执行过程中都存在,但只能(直接)在其局部范围内访问.Local variables can be declared with a storage qualifier or storage class specifier to change the storage duration of the variable. The most commonly seen one is static; local variables with static storage duration exist throughout the execution of the program but are only (directly) accessible within their local scope.如果尝试通过传递回写传递static局部变量,则编译器将产生错误,指示该变量没有自动存储持续时间.您必须以与实例变量(具有已分配存储期限的实例变量)相同的方式处理此类变量.If you attempt to pass a static local variable with pass-by-writeback the compiler will produce an error indicating the variable does not have automatic storage duration. You must handle such variables in the same way as instance variables (which have allocated storage duration). __block存储限定符是作为块的一部分和规范状态引入(Objective-)C:The __block storage qualifier was introduced into (Objective-)C as part of blocks and the specification states:因此,像实例变量一样,__block局部变量的作用就好像它已分配了存储持续时间一样,因此根据回写传递的规范,此类变量不能使用,因为它没有自动存储持续时间. ..So a __block local variable acts as if it has allocated storage duration, just like instance variables, and so by the specification of pass-by-writeback such a variable cannot be used as it does not have automatic storage duration... 但是使用撰写本文时的最新工具(Xcode 7.2,Clang 7.0.2)__block合格的局部变量由传递回写支持,并且其处理方式与那些相同.具有自动存储期限-使用隐藏的__autoreleasing临时目录.However with the tools current at the time of writing (Xcode 7.2, Clang 7.0.2) __block qualified local variables are supported by pass-by-writeback and are handle the same as those with automatic storage duration - a hidden __autoreleasing temporary is used. 该文件似乎没有记录.从某种意义上说,无论编译与否,使用它都是安全的",并且一旦编译,即使工具改变了,代码也仍然可以工作,并且以后也不能再次编译了...至少在不处理变量的情况下与必须处理实例变量相同).Having said that it is "safe" to use in the sense that it will either compile or not, and once compiled the code will work even if the tools change and it cannot be compiled again in the future... (at least without handling the variable the same was as instance variables must be handled).可以接受它的原因可以从对传递回写的限制(强调):The reason why it can be accepted can be gleaned from the rationale for the restrictions on pass-by-writeback (emphasis added):参数形式的限制有两个目的.首先,它使得无法将数组的地址传递给参数,从而避免了将数组"参数误认为是输出参数的严重风险. 第二,由于下面的实现,使得用户看到混淆的混叠问题的可能性大大降低,以下实现中,在原始参数变量中没有立即看到他们存储在写回临时文件中的信息.The restriction in the form of the argument serves two purposes. First, it makes it impossible to pass the address of an array to the argument, which serves to protect against an otherwise serious risk of mis-inferring an "array" argument as an out-parameter. Second, it makes it much less likely that the user will see confusing aliasing problems due to the implementation, below, where their store to the writeback temporary is not immediately seen in the original argument variable.传递回写不支持实例变量是没有技术原因的,但是由于混叠会引起混淆. __block变量位于自动变量和分配变量之间,因此,当前的工具编写者可能选择将它们与前者而不是后者分组以进行传递回写.There is no technical reason why instance variables could not be supported by pass-by-writeback, but it could be confusing due to aliasing. __block variables lie somewhere between automatic and allocated ones, so maybe the current tool writers choose to group them with the former rather than the latter for pass-by-writeback. 这篇关于处理ARC中的指针对指针所有权问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 1403页,肝出来的..
09-08 06:09