[英]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
”......我们拥有一个对象,由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
将导致运行时错误,因为您无法释放不属于您的对象。
如果在[str release]
之前调用它,我们实际上可以使用[str2 release]
[str release]
。 如果我们这样做,那么行[str release]
将导致错误,因为现在str
和str2
都是悬空指针,并且据说当第一次将release
发送到对象时,引用计数变为0,并且dealloc
是立即调用,内存由C函数free()
释放。
以上是否正确,或者还有其他问题需要纠正?
不要在管理内存方面考虑它,而是在对象所有权方面。 在分配,保留或复制对象时,您将获得对象的所有权。 您有责任准确发布您拥有的对象,而不是其他对象。
在你的例子中,对str2
的赋值不取得对象的所有权,但是如果你真的需要第二个“拥有”引用它,那么你应该做[str2 retain]
,之后它不是一个错误[str release]; [str2 release];
[str release]; [str2 release];
。 这也是使用ARC自动发生的情况,除非您将str2
注释为弱引用。 (当然,在这个简单的情况下,编译器可以在内部优化不必要的保留/释放。)
你的猜测是正确的:本书使用模糊语言(即使含义是正确的),以简化指针:
您拥有str
和str2
指向的对象。
这当然意味着你只能释放一次对象(或者更确切地说它通常被保留 - 在你的例子中,一次隐含地,通过alloc
),并且你是否通过str
或str2
(或任何其他方法)这样做是无关紧要的。
实际上,您应该将变量视为拥有变量。 这使得跟踪保留/释放对变得更加容易,并且您不能依赖于这样的事实,即没有人在其间的某处改变其中一个变量的值。
将所有指向解除分配的实例的变量设置为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,指向资源的所有 (引用计数)指针都是其共享所有者。 在这种情况下, 所有指针都负责跟踪对象引用计数,并在确定它们是唯一所有者并超出范围后释放该对象。
重申:所有权不是客观的。 所有权是指向对象的指针 ,这些指针的所有者,但只有当这些指针可能在某些情况下被释放。 如果没有方案可以释放资源,则指针是非拥有的。 在这种情况下,他们被称为弱者 。
如果对象拥有自己(因为所有指针都很弱), 弱指针的概念就没有意义。
如果释放str
或str2
,则释放内存位置str
和str2
指向的位置。 因此,您只需要调用str
或str2
,而不是两者,因为它们指向相同的内存位置。
我不明白你拥有一个变量是什么意思,据我所知,指针可以指向内存中的一块空间,仅此而已。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.