在一本书中,说如下:
那么你怎么知道对象何时拥有,以及由谁拥有?考虑一下
以下示例:
NSString *str = [[NSString alloc] initWithString:@”Hello”];
NSString *str2 = str;
在此示例中,您使用 alloc
关键字 str
,所以你拥有 str
。
因此,您需要在不再需要时释放它。然而,
str2
只是指着 str
,所以你不拥有 str2
,意思是你
不需要发布 str2
当你完成使用它。
我认为所有权是按对象而不是变量或指针...所以我们不能说我们“拥有” str
“或”拥有 str2
“......我们拥有一个物体,任何一个物体都指向它 str
要么 str2
,如果我们使用 [str release]
要么 [str2 release]
,它都是一样的。
另一种描述是:
例如,考虑上一节中使用的示例:
NSString *str = [[NSString alloc] initWithString:@”Hello”];
NSString *str2 = str;
[str release];
[str2 release]; //---this is not OK as you do not own str2---
试图释放 str2
将导致运行时错误,因为您
无法释放不属于您的对象。
我们实际上可以使用 [str2 release]
如果以前叫过 [str release]
。如果我们这样做,那么就行 [str release]
因为现在会导致错误 str
以及 str2
都是悬挂的指针,据说是什么时候 release
第一次被发送到对象,引用计数变为0,并且 dealloc
被立即调用,内存被C函数释放 free()
。
以上是否正确,或者还有其他问题需要纠正?
不要在管理内存方面考虑它,而是在对象所有权方面。在分配,保留或复制对象时,您将获得对象的所有权。您有责任准确发布您拥有的对象,而不是其他对象。
在您的示例中,分配给 str2
不取得对象的所有权,但如果你真的需要第二个“拥有”引用它,那么你应该这样做 [str2 retain]
之后,这不是一个错误 [str release]; [str2 release];
。这也是使用ARC自动发生的情况,除非您注释 str2
作为一个弱的参考。 (当然,在这个简单的情况下,编译器可以在内部优化不必要的保留/释放。)
你的猜测是正确的:本书使用模糊语言(即使含义是正确的),以简化指针:
你拥有那个对象 str
和 str2
指向。
这当然意味着你只能释放一次对象(或者更确切地说,它被保留了 - 一次在你的例子中,隐含地,通过 alloc
),以及你是否这样做 str
要么 str2
(或任何其他方式)是微不足道的。
实际上,您应该将变量视为拥有变量。这使得跟踪保留/释放对变得更加容易,并且您不能依赖于这样的事实,即没有人在其中某处改变其中一个变量的值。
设置指向解除分配的实例的所有变量是一种很好的做法(但不是必需的) nil
之后。
深入研究一下技术细节(真正应该被视为它们的内容:实现细节;私有API的工件):
从技术上讲,没人 拥有 物体。该对象具有保留次数的计数器(您可以通过调用找到它 anObject retainCount
- 但你不应该,尤其是因为有些对象有一个伪造的retainCount,因为它真的没有你的担心)。当一个物体是 alloc
ed,其retainCount为1.每次发送 retain
(“保留”),其retainCount上升1,每次发送时 release
(“它被释放”),其retainCount减少1。
一旦对象的retainCount达到零,它就会被释放(和它的 dealloc
方法被称为)。
谁发送了所有这些 retain
/release
消息(以及通过哪些变量)并不重要。
再说一遍:这些是实现细节。它们是Objective-C / Cocoa进行内存管理的工件。像任何私人API一样对待它们:好奇,但从不依赖于内部。只使用公共API(在这种情况下, retain
/release
生产代码中的自动释放池。
注意:某些对象(例如某些单例)会覆盖默认的保留/释放方法。永远不要相信 retainCount
你从一个物体获得,而不是好奇心(看看的retainCount) [UIColor clearColor]
例如)。
有关此主题的更多想法, 这个问题 它的答案可能是一个很好的总结/起点。
那说, 考虑切换到ARC,这将摆脱你几乎所有的内存管理麻烦。
我认为所有权是按对象而不是变量或指针...所以我们
不能说我们“拥有str”或“拥有str2”......我们拥有一个对象,就是这样
str或str2指向的,如果我们使用[str release]或[str2
发布],它都是一样的。
这是对的。
我认为作者所说的“我们拥有str”意味着你拥有那个字符串实例。不是指针或变量。理论上你可以使用另一个指针释放对象。但是使用用于初始化对象的变量来释放通常是个更好的主意。
我认为 其他答案是错误的或不完整的。
所有权由谁发布资源定义。 对象不(通常)拥有 本身, 它是 拥有的。
再说一遍:所有者是负责释放记忆的人。
在你的代码中, str
宣布了对象的所有权, str2
没有。为了 str2
也拥有对象(到 分享 str
的所有权),你需要 retain
它:
[str2 retain];
现在你可以稍后说,
[str2 release];
放弃 str2
对所有权的主张,同样适用 str
。
另一方面,使用ARC, 所有 (引用计数)指向资源的指针是它的共享所有者。在这种情况下, 所有指针负责跟踪对象引用计数,并在确定它们是唯一所有者并超出范围后释放该对象。
重申:所有权是 不 按对象。所有权是指针 至 一个对象,以及那些指针的所有者,但仅限于此 如果 在某些情况下可能会发布这些指针。如果没有方案可以释放资源,则指针是非拥有的。在这种情况下,他们被称为 弱。
一个概念 弱指针 如果对象拥有自己是没有意义的(因为所有指针都很弱)。
如果你释放 str
要么 str2
,内存位置 str
和 str2
指向被释放。所以,你只需要打电话 str
要么 str2
而不是两者,因为它们指向相同的内存位置。
我不明白你拥有一个变量是什么意思,据我所知,指针可以指向内存中的一块空间,仅此而已。