繁体   English   中英

在Objective-C中,所有权是对象,而不是变量或指针?

[英]In Objective-C, the ownership is for object, not variable or pointers?

在一本书中,说如下:

那么你怎么知道对象何时拥有,以及由谁拥有? 请考虑以下示例:

 NSString *str = [[NSString alloc] initWithString:@”Hello”]; NSString *str2 = str; 

在此示例中,您对str使用alloc关键字,因此您拥有str 因此,您需要在不再需要时释放它。 但是, str2只是指向str ,所以你不拥有str2 ,这意味着你在使用它时不需要释放str2

我认为所有权是按对象而不是变量或指针...所以我们不能说我们“拥有str ”或“拥有str2 ”......我们拥有一个对象,由strstr2 ,如果我们使用[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将导致运行时错误,因为您无法释放不属于您的对象。

如果在[str release]之前调用它,我们实际上可以使用[str2 release] [str release] 如果我们这样做,那么行[str release]将导致错误,因为现在strstr2都是悬空指针,并且据说当第一次将release发送到对象时,引用计数变为0,并且dealloc是立即调用,内存由C函数free()释放。

以上是否正确,或者还有其他问题需要纠正?

不要在管理内存方面考虑它,而是在对象所有权方面。 在分配,保留或复制对象时,您将获得对象的所有权。 您有责任准确发布您拥有的对象,而不是其他对象。

在你的例子中,对str2的赋值不取得对象的所有权,但是如果你真的需要第二个“拥有”引用它,那么你应该做[str2 retain] ,之后它不是一个错误[str release]; [str2 release]; [str release]; [str2 release]; 这也是使用ARC自动发生的情况,除非您将str2注释为弱引用。 (当然,在这个简单的情况下,编译器可以在内部优化不必要的保留/释放。)

你的猜测是正确的:本书使用模糊语言(即使含义是正确的),以简化指针:

您拥有strstr2指向的对象。

这当然意味着你只能释放一次对象(或者更确切地说它通常被保留 - 在你的例子中,一次隐含地,通过alloc ),并且你是否通过strstr2 (或任何其他方法)这样做是无关紧要的。

实际上,您应该将变量视为拥有变量。 这使得跟踪保留/释放对变得更加容易,并且您不能依赖于这样的事实,即没有人在其间的某处改变其中一个变量的值。

将所有指向解除分配的实例的变量设置为nil是一种很好的做法(但不是必需的)。

深入研究技术细节(真正应该被视为它们的内容:实现细节;私有API的工件):

从技术上讲,没有人拥有这个对象。 该对象有一个计数器,它保留了它的次数(你可以通过调用anObject retainCount找到anObject retainCount - 但你不应该,尤其是因为一些对象有一个伪造的retainCount,因为它真的没有你关心的)。 当一个对象alloc版,其retainCount是1.每个被发送的时间retain (“是保留”),其通过retainCount 1上升,并且每次发送时release (“被释放”),其retainCount减少1。

一旦对象的retainCount达到零,就会释放它(并调用它的dealloc方法)。

谁发送了所有这些retain / release消息(以及通过哪些变量)并不重要。

再说一遍:这些是实现细节。 它们是Objective-C / Cocoa进行内存管理的工件。 像任何私人API一样对待它们:好奇,但从不依赖于内部。 只在生产代码中使用公共API(在本例中为retain / release和自动释放池)。

注意:某些对象(例如某些单例)会覆盖默认的保留/释放方法。 永远不要相信你从对象获得的retainCount ,除了好奇心(例如,查看[UIColor clearColor][UIColor clearColor] )。

有关此主题的更多想法, 这个问题及其答案可能是一个很好的总结/起点。

也就是说, 考虑切换到ARC ,这将摆脱几乎所有的内存管理问题。

我认为所有权是按对象而不是变量或指针...所以我们不能说我们“拥有str”或“拥有str2”......我们拥有一个对象,由str或str2指向,如果我们使用[str release]或[str2 release],它们都是一样的。

这是对的。

我认为作者所说的“我们拥有str”意味着你拥有那个字符串实例。 不是指针或变量。 理论上你可以使用另一个指针释放对象。 但是使用用于初始化对象的变量来释放通常是个更好的主意。

我认为其他答案是错误的或不完整的。

所有权由谁发布资源来定义。 对象不(通常)拥有自己 ,它是拥有的

再说一次:所有者是负责释放记忆的人。

在你的代码中, str声明了它对象的所有权, str2没有。 为了让str2也拥有对象( 共享 str的所有权),你需要retain它:

[str2 retain];

现在你可以稍后说,

[str2 release];

放弃str2对所有权的主张,同样适用于str

另一方面,使用ARC,指向资源的所有 (引用计数)指针都是其共享所有者。 在这种情况下, 所有指针都负责跟踪对象引用计数,并在确定它们是唯一所有者并超出范围后释放该​​对象。

重申:所有权不是客观的。 所有权是指向对象的指针 ,这些指针的所有者,但只有这些指针可能在某些情况下被释放。 如果没有方案可以释放资源,则指针是非拥有的。 在这种情况下,他们被称为弱者

如果对象拥有自己(因为所有指针都很弱), 弱指针的概念就没有意义。

如果释放strstr2 ,则释放内存位置strstr2指向的位置。 因此,您只需要调用strstr2 ,而不是两者,因为它们指向相同的内存位置。

我不明白你拥有一个变量是什么意思,据我所知,指针可以指向内存中的一块空间,仅此而已。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM