在一本书中,说如下:
那么你怎么知道对象何时拥有,以及由谁拥有?考虑一下
以下示例:
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,因为它真的没有你的担心)。当一个物体是 alloced,其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而不是两者,因为它们指向相同的内存位置。
我不明白你拥有一个变量是什么意思,据我所知,指针可以指向内存中的一块空间,仅此而已。