- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设对象具有一个属性:
@property (nonatomic, strong) Foo * bar;
@synthesize bar = _bar;
Foo **
,如本例中从
对象A 进行的调用:
Foo * temp = self.bar;
[objB doSomething:&temp];
self.bar = temp;
doSomething:
方法的正确声明是什么? bar
属性之前被释放了(从而获得了
temp
指向的实例的所有权)-我将如何告诉ARC移交拥有的引用?换句话说,如果我希望以下示例代码起作用,我将如何处理ARC问题?
Foo * temp = self.bar; // Give it a reference to some current value
[objB doSomething:&temp]; // Let it modify the reference
self.bar = nil; // Basically release whatever we have
_bar = temp; // Since we're getting back an owning reference, bypass setter
@implementation ObjectA
@synthesize bar = _bar;
- (void)someMethod
{
ObjectB * objB = [[ObjectB alloc] initWithFoo:&_bar];
// objB handed off somewhere and eventually it's "doSomething" method is called.
}
@end
@implementation ObjectB
{
Foo * __autoreleasing * _temp;
}
- (id)initWithFoo:(Foo * __autoreleasing *)temp
{
id self = [super init];
if (self)
{
_temp = temp;
}
return self;
}
- (void)doSomething
{
...
*_temp = [[Foo alloc] init];
...
}
@end
passing address of non-local object to __autoreleasing parameter for write-back
最佳答案
ARC需要知道对象引用的所有权,以便它可以确定何时释放它,等等。对于任何变量(本地,实例或全局),ARC都有确定所有权的规则。通过推断或通过显式属性。这等同于程序员需要在ARC之前跟踪所有权。
但是,如果引用变量,会发生什么?您无法(在ARC之前)自己编写代码,该代码接受对变量的引用,并且无论该变量的所有权如何,该代码始终可以正常工作-因为您不知道是否需要释放变量等。您无法构建适用于变量(从变化的意义上来说)未知所有权的代码。
ARC面临相同的问题,其解决方案是推断或接受指定引用变量所有权的显式属性,然后要求调用者安排对要传递的具有适当所有权的变量的引用。后一点可能需要使用隐藏的临时变量。这在specification中称为“最差的解决方案”,并称为“回写传递”。
问题的第一部分:
Foo * temp = self.bar;
[objB doSomething:&temp];
self.bar = temp;
- Can this, or something similar, be done legitimately?
temp
被推断为
strong
,一些幕后的东西碰巧通过引用
doSomething:
传递给它。
- What is the correct declaration for the doSomething: method?
- (void) doSomething:(Foo **)byRefFoo
ARC推断
byRefFoo
的类型为
Foo * __autoreleasing *
-对自动释放引用的引用。这就是“传递回写”所要求的。
temp
是本地代码。用实例变量执行此操作是不正确的(如您在EDIT中所发现的)。假设该参数在标准“输出”模式下使用并且
doSomething:
返回时已分配了任何更新的值,则它也仅对
有效。这两个都是因为传递回写方式是“最差的解决方案”的一部分。Foo
,我们将使用Breadcrumbs
类型;这实际上是一个包装的NSString
,它跟踪每个init
,retain
,release
,autorelease
和dealloc
(以及您几乎会在下面看到的),因此我们可以看到发生了什么。 Breadcrumbs
的编写方式并不重要。@implementation ByRef
{
Breadcrumbs *instance; // __strong inferred
}
更改通过引用传递的值的方法:- (void) indirect:(Breadcrumbs **)byRef // __autoreleasing inferred
{
*byRef = [Breadcrumbs newWith:@"banana"];
}
一个简单的indirect:
包装器,因此我们可以看到它传递了什么以及何时返回:- (void) indirectWrapper:(Breadcrumbs **)byRef // __autoreleasing inferred
{
NSLog(@"indirect: passed reference %p, contains %p - %@, owners %lu", byRef, *byRef, *byRef, [*byRef ownerCount]);
[self indirect:byRef];
NSLog(@"indirect: returned");
}
以及演示在局部变量上调用indirect:
的方法(想象中的local
):- (void) demo1
{
NSLog(@"Strong local passed by autoreleasing reference");
Breadcrumbs *local; // __strong inferred
local = [Breadcrumbs newWith:@"apple"];
NSLog(@"local: addr %p, contains %p - %@, owners %lu", &local, local, local, [local ownerCount]);
[self indirectWrapper:&local];
NSLog(@"local: addr %p, contains %p - %@, owners %lu", &local, local, local, [local ownerCount]);
}
@end
现在,执行demo1
的一些代码将自动释放池本地化,以便我们可以查看分配,释放的内容以及何时:ByRef *test = [ByRef new];
NSLog(@"Start demo1");
@autoreleasepool
{
[test demo1];
NSLog(@"Flush demo1");
}
NSLog(@"End demo1");
执行上述操作会在控制台上产生以下内容:ark[2041:707] Start demo1
ark[2041:707] Strong local passed by autoreleasing reference
ark[2041:707] >>> 0x100176f30: init
ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 1
ark[2041:707] indirect: passed reference 0x7fff5fbfedb8, contains 0x100176f30 - apple, owners 1
ark[2041:707] >>> 0x100427d10: init
ark[2041:707] >>> 0x100427d10: autorelease
ark[2041:707] indirect: returned
ark[2041:707] >>> 0x100427d10: retain
ark[2041:707] >>> 0x100176f30: release
ark[2041:707] >>> 0x100176f30: dealloc
ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100427d10 - banana, owners 2
ark[2041:707] >>> 0x100427d10: release
ark[2041:707] Flush demo1
ark[2041:707] >>> 0x100427d10: release
ark[2041:707] >>> 0x100427d10: dealloc
ark[2041:707] End demo1
[>>>“行来自Breadcrumbs
。]只需跟随对象(0x100 ...)和变量(0x7fff ...)的地址,就很清楚了...ark[2041:707] Start demo1
ark[2041:707] Strong local passed by autoreleasing reference
ark[2041:707] >>> 0x100176f30: init
ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 1
在这里,我们看到[Breadcrumbs newWith:@"apple"]
在地址0x100176f30
处创建了一个对象。这存储在local
中,其地址为0x7fff5fbfedc0
,并且该对象具有1个所有者(local
)。ark[2041:707] indirect: passed reference 0x7fff5fbfedb8, contains 0x100176f30 - apple, owners 1
这是隐藏的变量:由于indirect:
需要引用自动释放变量,因此ARC创建了一个新变量,其地址为0x7fff5fbfedb8
,并将对象引用(0x100176f30
)复制到该变量中。ark[2041:707] >>> 0x100427d10: init
ark[2041:707] >>> 0x100427d10: autorelease
ark[2041:707] indirect: returned
在indirect:
内部,将创建一个新对象,并且ARC在分配它之前会自动释放它-因为传递的引用引用了一个自动释放变量。Note: ARC does not need to do anything with the previous contents (
0x100176f30
) of the referenced variable (0x7fff5fbfedb8
) as it is autoreleasing and hence not its responsibility. I.e. what "autoreleasing ownership" means is that any reference assigned must have already been effectively autoreleased. You'll see when creating the hidden variable ARC did not actually retain and autorelease its contents - it did not need to do this as it knows there is a strong reference (inlocal
) to the object which it is managing. [In the last example below ARC does have to manage this assignment but it still manages to avoid using the autorelease pool.]
ark[2041:707] >>> 0x100427d10: retain
ark[2041:707] >>> 0x100176f30: release
ark[2041:707] >>> 0x100176f30: dealloc
这些操作是由于将隐藏变量的值复制(即写回调用中的“写回”)到local
中而导致的。 release / dealloc用于local
中的旧强引用,而retain用于隐藏变量(已由indirect:
自动释放)引用的对象。Note: this writeback is why this only works for the "out" pattern of using pass-by-reference - you can't store the reference passed to
indirect:
as it is to a hidden local variable which is about to disappear...
ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100427d10 - banana, owners 2
因此,在调用local
引用新对象之后,它有2个所有者-local
占一个,另一个是autorelease
中的indirect:
ark[2041:707] >>> 0x100427d10: release
demo1
现在完成,因此ARC以local
释放对象ark[2041:707] Flush demo1
ark[2041:707] >>> 0x100427d10: release
ark[2041:707] >>> 0x100427d10: dealloc
ark[2041:707] End demo1
在demo1
返回本地化的@autoreleasepool
处理indirect:
挂起的自动发布之后,现在所有权为零,我们得到了dealloc
。ByRef
类中添加了strongIndirect:
,它指定它需要对强变量的引用:- (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
的虚构名称):- (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
类似的代码片段执行此操作,我们得到:1 ark[2041:707] Start demo2
2 ark[2041:707] Strong instance passed by strong reference
3 ark[2041:707] >>> 0x100176f30: init
4 ark[2041:707] instance: addr 0x100147518, contains 0x100176f30 - orange, owners 1
5 ark[2041:707] strongIndirect: passed reference 0x100147518, contains 0x100176f30 - orange, owners 1
6 ark[2041:707] >>> 0x100427d10: init
7 ark[2041:707] >>> 0x100176f30: release
8 ark[2041:707] >>> 0x100176f30: dealloc
9 ark[2041:707] strongIndirect: returned
10 ark[2041:707] instance: addr 0x100147518, contains 0x100427d10 - plum, owners 1
11 ark[2041:707] Flush demo2
12 ark[2041:707] End demo2
这比以前短了一点。这有两个原因:instance
)传递给期望引用强变量的方法(strongIndirect:
)时,ARC无需使用隐藏变量-上面第4行和第5行中的变量相同(0x100147518
)。strongIndirect:
中的引用变量很强,所以不需要在strongIndirect:
中存储自动发布的引用,然后在调用后写回该代码-ARC只是执行标准的强分配,第6-8行,没有什么要自动发布的之后(在第11和12行之间)。strongIndirect:
是否适用于强大的本地人? 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]);
}
使用我们的标准包装器执行此操作会产生:1 ark[2041:707] Start demo3
2 ark[2041:707] Strong local passed by strong reference
3 ark[2041:707] >>> 0x100176f30: init
4 ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 1
5 ark[2041:707] strongIndirect: passed reference 0x7fff5fbfedc0, contains 0x100176f30 - apple, owners 1
6 ark[2041:707] >>> 0x100427d20: init
7 ark[2041:707] >>> 0x100176f30: release
8 ark[2041:707] >>> 0x100176f30: dealloc
9 ark[2041:707] strongIndirect: returned
10 ark[2041:707] local: addr 0x7fff5fbfedc0, contains 0x100427d20 - plum, owners 1
11 ark[2041:707] >>> 0x100427d20: release
12 ark[2041:707] >>> 0x100427d20: dealloc
13 ark[2041:707] Flush demo3
14 ark[2041:707] End demo3
这几乎与前面的示例相同,只有两个小的区别:0x7fff5fbfedc0
),第4行和第5行__strong
添加到引用参数? - (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
,因此我们需要对其进行弱引用。] 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: returned
10 ark[2041:707] >>> 0x608000000d10: release
11 ark[2041:707] weakLocal: addr 0x7ffeefbfde58, contains 0x604000001060 - banana, owners 4
12 ark[2041:707] Flush demo4
13 ark[2041:707] >>> 0x604000001060: release
14 ark[2041:707] >>> 0x604000001060: dealloc
15 ark[2041:707] End demo4
16 ark[2041:707] >>> 0x608000000d10: release
17 ark[2041:707] >>> 0x608000000d10: dealloc
笔记:instance
相关-创建新值并在最后释放并释放-重要内容始于第4行weakLocal
的内容,请注意,将`instance'的强引用复制到此弱变量中不需要任何保留。 (注意:显示弱变量的内容确实涉及某些保留和释放操作,为清楚起见已将其省略。)0x7ffeefbfde40
)使用了一个隐藏变量(第6行,0x7ffeefbfde58
)。在强本地情况(demo1)中,ARC知道存储在此隐藏变量中的引用将保持有效,并避免使用自动释放池。在这种情况下,这不能保证,但是ARC仍然设法避免使用自动释放池:ARC保留了引用(第5行,retainWeakReference
是retain
的特殊版本,用于弱变量),并且在调用完成后与释放(行)保持平衡。 10)。与使用自动释放池相比,这会缩短强引用的寿命。0x604000001060
(第8行)中的自动释放的分配(indirectWrapper
)是平衡的。最后,当我们的instance
实例消失后,ARC会清理存储在0x608000000d10
(ByRef
)中的对象。__strong
来指定接收参数的类型。__weak
当地人。__block
变量What if my local variable is a
__block
type? I'm pretty sure this case is the same as an instance variable in that I need to either copy them to locals, or attribute the receiving parameter type with__strong
, but I'm curious about someone else's opinion.
The pass-by-writeback is ill-formed if the argument expression does not have a legal form:
•
&var
, wherevar
is a scalar variable of automatic storage duration with retainable object pointer type
static
;具有静态存储持续时间的局部变量在程序的整个执行过程中都存在,但只能(直接)在其局部范围内访问。static
局部变量,则编译器将产生一个错误,指示该变量没有自动存储时间。您必须以与实例变量(已分配存储持续时间)相同的方式处理此类变量。__block
storage qualifier作为块的一部分被引入到(Objective-)C中,并且规范状态如下:The
__block
storage qualifier is mutually exclusive to the existing local storage qualifiersauto
,register
, andstatic
. Variables qualified by__block
act as if they were in allocated storage and this storage is automatically recovered after last use of said variable.
__block
局部变量就像实例变量一样,就像分配了存储持续时间一样工作,因此根据回写传递的规范,由于该变量没有自动存储持续时间,因此无法使用...__block
合格的局部变量受传递回写的支持,并且其处理方式与自动存储持续时间相同-隐藏的__autoreleasing
临时变量是用过的。Rationale
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
变量介于自动变量和分配变量之间,因此,当前的工具编写者可能选择将它们与前者而不是后者分组,以进行传递回写。Note: Readers familiar with the implementation of blocks will know that a
__block
qualified local may be implemented as an optimisation with either automatic or allocated storage duration, depending on usage, and therefore wonder whether this impacts their use for pass-by-writeback. This does not appear to be the case.
关于objective-c - 处理ARC中的指针对指针所有权问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8814718/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!