何时“释放”设置属性/实例变量后?

发布于 2024-12-07 05:47:01 字数 465 浏览 1 评论 0原文

我们声明了一个属性:

@property (retain) MyClass *myProperty;

有什么区别

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];

Apple 示例代码中的这个与此

myProperty = [[MyClass alloc] init];

:编辑:

发布的原始代码应该是这个:

MyClass *aux = [[MyClass alloc] init];
self.myProperty = aux;
[aux release];

这是我的一个错误,但由于许多答案都涵盖了我的主题留下了原来的代码。

We have a property declared:

@property (retain) MyClass *myProperty;

What is the difference between this one from Apple example Code:

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];

and this one:

myProperty = [[MyClass alloc] init];

Edited:

The original code posted should have been this one:

MyClass *aux = [[MyClass alloc] init];
self.myProperty = aux;
[aux release];

It was an error of mine, but since many answers have covered the topic I have leave the original code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

人疚 2024-12-14 05:47:01

这通常是将属性设置为您创建的新值的正确方法。

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
self.myProperty = aux; // new value retain count 2; IMPORTANT: old value retain count decremented
[aux release]; // new value retain count 1, correct since it's retained by self

这在 init 方法中是可以接受的。

myProperty = [[MyClass alloc] init]; // new value retain count 1; there was no old value since the object just init'ed

您发布的代码是错误的。

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
myProperty = aux; // new value retain count 1
[aux release]; // new value retain count 0!! deallocated; myProperty points to invalid memory

下面的代码有一个微妙的错误。

self.myProperty = [[MyClass alloc] init]; // new value retain count 1 for alloc + 1 for assigned to retain property
[self.myProperty release]; // normally new value retain count 1, correct

但是,如果访问器以一种有趣的方式编写,并且 getter 不返回传递给 setter 的相同对象,您可能会遇到麻烦。例如,它可能返回某种代理对象。那么你就不会释放你分配的同一个对象。

This is generally the right way to set a property to a new value you've created.

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
self.myProperty = aux; // new value retain count 2; IMPORTANT: old value retain count decremented
[aux release]; // new value retain count 1, correct since it's retained by self

This is acceptable in the init method.

myProperty = [[MyClass alloc] init]; // new value retain count 1; there was no old value since the object just init'ed

The code you posted is wrong.

MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
myProperty = aux; // new value retain count 1
[aux release]; // new value retain count 0!! deallocated; myProperty points to invalid memory

The following code is subtly wrong.

self.myProperty = [[MyClass alloc] init]; // new value retain count 1 for alloc + 1 for assigned to retain property
[self.myProperty release]; // normally new value retain count 1, correct

However you might get into trouble if the accessors are written in a funny way, and the getter doesn't return the same object you passed into the setter. Perhaps it returns some sort of proxy object, for example. Then you would not be releasing the same object you alloc'ed.

原来分手还会想你 2024-12-14 05:47:01

首先,为了稍微澄清一下声明属性的含义,我将对其进行一些解释。

当你声明一个属性时,你实际上是在声明两个方法,即该特定类属性的 getter 和 setter。当您将属性声明为 retain 时,您实际上是在说,当您通过 setter 方法设置该属性时,它将被保留。这基本上意味着它的保留计数将增加。

为了使用声明的属性设置类属性,您可以使用点语法,例如 self.myProperty 或 setter 方法,例如 -(void)setMyProperty:(MyClass*)newMyClass

因此,在您的代码中,即使您声明了一个属性,您也没有使用它,因为您没有使用上述任何方法。

现在,

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
  1. 您分配一个 MyClass 对象,现在该对象的保留计数为 1。
  2. 您将其分配给您的类属性(不使用该属性),因此保留计数仍然为 1。
  3. 您释放该对象对象,因此它的保留计数为 0 并且被释放。

myProperty = [[MyClass alloc] init];

  1. 您分配一个 MyClass 对象(它的保留计数为 1)并为其分配类属性 myProperty

因此,总而言之,在第一种情况下,您在内存中创建并对象,然后处置它,而在第二种情况下,您正在创建它,但它永远不会被处置。

Firs of all, just to clarify a little bit what declaring a property means I will explain it a little.

When you declare a property, you are actually declaring two methods, a getter and a setter for that particular class attribute. When you declare a property as retain you are actually saying that when you set that property through the setter method, it will be retained. That basically means that its retain count will be incremented.

In order to set the class attribute using the property declared, you can either use dot syntax, e.g. self.myProperty or the setter method, e.g. -(void)setMyProperty:(MyClass*)newMyClass,

So, in your code, even though you are declaring a property, you are not making use of it because you are not using any of the methods stated above.

Now,

MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
  1. You alloc a MyClass object, now that object has retain count of 1.
  2. You assign it to your class attribute (w/o using the property) so the retain count is still 1.
  3. You release that object so its retain count is 0 and it gets released.

myProperty = [[MyClass alloc] init];

  1. You alloc a MyClass object (it has retain count of 1) and assign it your class attribute myProperty.

So, to sum up, in the first case you create and object in memory and then you dispose it, whereas in the second one you are creating it but it never gets disposed.

蔚蓝源自深海 2024-12-14 05:47:01
self.myProperty = [[MyClass alloc] init];  // this will leak
myProperty = [[MyClass alloc] init];  // this will NOT leak

第一行泄漏是因为它使用属性设置器来分配新对象,并且该属性具有保留的内存模型。因此,除了分配中的分配之外,您还可以从属性的设置器中获得保留。

但是,第二行不会泄漏,因为它不使用属性的 setter,而是使用其后面的私有变量。一般来说,除了 init 之外,您希望在任何地方使用 setter。

由于属性设置器会增加保留计数(对于保留/复制内存模型),因此在属性分配中看到自动释放的情况并不罕见,例如:

self.myProperty = [[[MyClass alloc] init] autorelease];  // Yeah, no leak now

如果您想真正了解它,则覆盖的设置器可能看起来像这样:

- (void) setMyProperty:(MyClass*)newMyProperty
{
   MyClass *oldValue = _myProperty;
   // replace retain with copy if you want copy to be memory model
   _myProperty = [newMyProperty retain];   
   [oldValue release];  // release last in case newMyProperty == oldValue

   [...] // super cool setter behavior here
}
self.myProperty = [[MyClass alloc] init];  // this will leak
myProperty = [[MyClass alloc] init];  // this will NOT leak

The first line leaks because it is using the property setter to assign a new object and the property has a memory model of retain. So, in addition to the alloc in the assignment, you get a retain from the property's setter.

However, the second line will not leak as it is not using the property's setter but the private variable behind it. Generally speaking, you want to use the setter everywhere except in init.

Because property setters increase the retain count (for retain / copy memory models), it's not uncommon to see an autorelease in property assignments like:

self.myProperty = [[[MyClass alloc] init] autorelease];  // Yeah, no leak now

If you want to really wrap your head around it, an overridden setter might look something like this:

- (void) setMyProperty:(MyClass*)newMyProperty
{
   MyClass *oldValue = _myProperty;
   // replace retain with copy if you want copy to be memory model
   _myProperty = [newMyProperty retain];   
   [oldValue release];  // release last in case newMyProperty == oldValue

   [...] // super cool setter behavior here
}
£噩梦荏苒 2024-12-14 05:47:01

在第一种情况下,myProperty 的保留计数为 0。
在第二种情况下,myProperty 的保留计数为 1。
如果您在第一种情况下使用 self.myProperty = aux ,则 aux 和 myProperty 的保留计数将为 1。

In first case myProperty have retainCount 0.
In second case myProperty have retainCount 1.
If you will use self.myProperty = aux in first case then retainCount of aux and myProperty will be 1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文