简体   繁体   English

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

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

In a book, the following is said: 在一本书中,说如下:

So how do you know when an object is owned, and by whom? 那么你怎么知道对象何时拥有,以及由谁拥有? Consider the following example: 请考虑以下示例:

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

In this example, you use the alloc keyword for str , so you own str . 在此示例中,您对str使用alloc关键字,因此您拥有str Therefore, you need to release it when it's no longer needed. 因此,您需要在不再需要时释放它。 However, str2 is simply pointing to str , so you do not own str2 , meaning you need not release str2 when you are done using it. 但是, str2只是指向str ,所以你不拥有str2 ,这意味着你在使用它时不需要释放str2

I thought ownership is by object, not variable or pointer... so we can't say we "own str " or "own str2 "... we own an object, which is pointed to by either str or str2 , and if we use [str release] or [str2 release] , it is all the same. 我认为所有权是按对象而不是变量或指针...所以我们不能说我们“拥有str ”或“拥有str2 ”......我们拥有一个对象,由strstr2 ,如果我们使用[str release][str2 release] ,它们都是一样的。

The other description is: 另一种描述是:

For example, consider the example used in the previous section: 例如,考虑上一节中使用的示例:

 NSString *str = [[NSString alloc] initWithString:@”Hello”]; NSString *str2 = str; [str release]; [str2 release]; //---this is not OK as you do not own str2--- 

Attempting to release str2 will result in a runtime error because you cannot release an object not owned by you. 尝试释放str2将导致运行时错误,因为您无法释放不属于您的对象。

We can actually use [str2 release] if that is called before [str release] . 如果在[str release]之前调用它,我们实际上可以使用[str2 release] [str release] If we do that, then the line [str release] will cause an error because now str as well as str2 are both dangling pointers, and supposedly when release was sent to the object the first time, the reference count became 0, and dealloc was called immediately, and the memory was freed by the C function free() . 如果我们这样做,那么行[str release]将导致错误,因为现在strstr2都是悬空指针,并且据说当第一次将release发送到对象时,引用计数变为0,并且dealloc是立即调用,内存由C函数free()释放。

Is the above correct, or maybe there is something else to be corrected? 以上是否正确,或者还有其他问题需要纠正?

Don't think of it in terms of managing memory, but in terms of object ownership. 不要在管理内存方面考虑它,而是在对象所有权方面。 You obtain ownership of an object when you allocate it, retain it, or copy it. 在分配,保留或复制对象时,您将获得对象的所有权。 You are responsible for releasing exactly the objects you own, not others. 您有责任准确发布您拥有的对象,而不是其他对象。

In your example the assignment to str2 does not take ownership of the object, but if you really need a second "owning" reference to it, then you ought to do [str2 retain] , after which it is not an error to do [str release]; [str2 release]; 在你的例子中,对str2的赋值不取得对象的所有权,但是如果你真的需要第二个“拥有”引用它,那么你应该做[str2 retain] ,之后它不是一个错误[str release]; [str2 release]; [str release]; [str2 release]; . This is also what would happen automatically using ARC, unless you annotated str2 as a weak reference. 这也是使用ARC自动发生的情况,除非您将str2注释为弱引用。 (Of course in this simple case the unnecessary retain/release could be optimized away internally by the compiler.) (当然,在这个简单的情况下,编译器可以在内部优化不必要的保留/释放。)

Your guess is correct: The book uses fuzzy language (even though the implications are correct) in an effort to simplify pointers away: 你的猜测是正确的:本书使用模糊语言(即使含义是正确的),以简化指针:

You own the object that str and str2 point to. 您拥有strstr2指向的对象。

This of course means that you can only release the object once (or rather however often it was retained - once in your example, implicitly, by alloc ), and whether you do so through str or str2 (or any other means) is insignificant. 这当然意味着你只能释放一次对象(或者更确切地说它通常被保留 - 在你的例子中,一次隐含地,通过alloc ),并且你是否通过strstr2 (或任何其他方法)这样做是无关紧要的。

In practice, you should treat your variables as if you owned them, though. 实际上,您应该将变量视为拥有变量。 This makes it much easier to keep track of retain/release pairs, and you cannot rely on the fact that nobody changed the value of one of these variables somewhere in between. 这使得跟踪保留/释放对变得更加容易,并且您不能依赖于这样的事实,即没有人在其间的某处改变其中一个变量的值。

It is good practice (but not necessary) to set all variables that point to a deallocated instance to nil afterwards. 将所有指向解除分配的实例的变量设置为nil是一种很好的做法(但不是必需的)。

To delve a bit into the technical details (which really should be treated as what they are: Implementation details; artifacts of a private API): 深入研究技术细节(真正应该被视为它们的内容:实现细节;私有API的工件):

Technically, nobody owns the object. 从技术上讲,没有人拥有这个对象。 The object has a counter of the number of times it was retained (which you can find out by calling anObject retainCount - but you shouldn't, not least because some objects have a bogus retainCount, and because it's really none of your concern). 该对象有一个计数器,它保留了它的次数(你可以通过调用anObject retainCount找到anObject retainCount - 但你不应该,尤其是因为一些对象有一个伪造的retainCount,因为它真的没有你关心的)。 When an object is alloc ed, its retainCount is 1. Every time it is sent retain ("it is retained"), its retainCount goes up by 1, and every time it is sent release ("it is released"), its retainCount is decreased by 1. 当一个对象alloc版,其retainCount是1.每个被发送的时间retain (“是保留”),其通过retainCount 1上升,并且每次发送时release (“被释放”),其retainCount减少1。

Once the retainCount of an object reaches zero, it is deallocated (and its dealloc method is called). 一旦对象的retainCount达到零,就会释放它(并调用它的dealloc方法)。

Who sent all those retain / release messages (and through which variables) is not important. 谁发送了所有这些retain / release消息(以及通过哪些变量)并不重要。

Again: These are implementation details. 再说一遍:这些是实现细节。 They're artifacts of the way Objective-C/Cocoa do their memory management. 它们是Objective-C / Cocoa进行内存管理的工件。 Treat them like any private API: It's good to be curious, but never rely on internals. 像任何私人API一样对待它们:好奇,但从不依赖于内部。 Only ever use the public API (in this case, retain / release and autorelease pools) in production code. 只在生产代码中使用公共API(在本例中为retain / release和自动释放池)。

NOTE: Some objects (for instance some singletons) override the default retain/release methods. 注意:某些对象(例如某些单例)会覆盖默认的保留/释放方法。 Never trust the retainCount you get from an object, other than for curiosity (look at the retainCount of [UIColor clearColor] for instance). 永远不要相信你从对象获得的retainCount ,除了好奇心(例如,查看[UIColor clearColor][UIColor clearColor] )。

For more thoughts on this topic, this question and its answers are probably a nice summary/starting point. 有关此主题的更多想法, 这个问题及其答案可能是一个很好的总结/起点。

That said, consider switching to ARC , which will rid you of almost all memory management troubles. 也就是说, 考虑切换到ARC ,这将摆脱几乎所有的内存管理问题。

I thought ownership is by object, not variable or pointer... so we can't say we "own str" or "own str2"... we own an object, which is pointed to by either str or str2, and if we use [str release] or [str2 release], it is all the same. 我认为所有权是按对象而不是变量或指针...所以我们不能说我们“拥有str”或“拥有str2”......我们拥有一个对象,由str或str2指向,如果我们使用[str release]或[str2 release],它们都是一样的。

This is correct. 这是对的。

I think what the author means by "we own str" ist that you own that string instance. 我认为作者所说的“我们拥有str”意味着你拥有那个字符串实例。 Not the pointer or the variable. 不是指针或变量。 You could theoretically release the object using an other pointer. 理论上你可以使用另一个指针释放对象。 But it's generally a better idea to release using the variable you used to initialize the object. 但是使用用于初始化对象的变量来释放通常是个更好的主意。

I think the other answers are wrong or incomplete. 我认为其他答案是错误的或不完整的。

Ownership is defined by who releases a resource. 所有权由谁发布资源来定义。 An object doesn't (usually) own itself , it is owned . 对象不(通常)拥有自己 ,它是拥有的

Again: the owner is whoever is responsible for releasing the memory. 再说一次:所有者是负责释放记忆的人。

In your code, str has declared its ownership of the object, str2 has not. 在你的代码中, str声明了它对象的所有权, str2没有。 In order for str2 to also own the object (to share str 's ownership), you'd need to retain it: 为了让str2也拥有对象( 共享 str的所有权),你需要retain它:

[str2 retain];

Now you could later say, 现在你可以稍后说,

[str2 release];

to relinquish str2 's claim to ownership, and the same goes for str . 放弃str2对所有权的主张,同样适用于str

On the other hand, with ARC, all (reference-counting) pointers to a resource are its shared owners. 另一方面,使用ARC,指向资源的所有 (引用计数)指针都是其共享所有者。 In this scenario, all pointers are responsible for keeping track of the object reference count, and releasing the object once they determine that they are the sole owners and go out of scope. 在这种情况下, 所有指针都负责跟踪对象引用计数,并在确定它们是唯一所有者并超出范围后释放该​​对象。

To reiterate: Ownership is not by object. 重申:所有权不是客观的。 Ownership is by pointers to an object, and the owner of those pointers, but only if those pointers might be released in some scenario. 所有权是指向对象的指针 ,这些指针的所有者,但只有这些指针可能在某些情况下被释放。 Pointers are non-owning if there is no scenario in which they would release the resource. 如果没有方案可以释放资源,则指针是非拥有的。 In this case, they are called weak . 在这种情况下,他们被称为弱者

The concept of a weak pointer would make no sense if objects owned themselves (since all pointers would be weak). 如果对象拥有自己(因为所有指针都很弱), 弱指针的概念就没有意义。

If you release either str or str2 , the memory location str and str2 points to is freed. 如果释放strstr2 ,则释放内存位置strstr2指向的位置。 So, you only have to call str or str2 , not both, because they point to the same memory location. 因此,您只需要调用strstr2 ,而不是两者,因为它们指向相同的内存位置。

I don't understand what you mean by 'owning' a variable, as far as I know a pointer can point to a piece of space in the memory, and nothing more. 我不明白你拥有一个变量是什么意思,据我所知,指针可以指向内存中的一块空间,仅此而已。

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

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