Цель C - Вопрос управления памятью? - PullRequest
0 голосов
/ 18 ноября 2010

Я знаю, что при установке сохраненного свойства для выделенного объекта он увеличивает счетчик сохранения объекта, поэтому мне нужно освободить его (3-я строка, первый блок кода)

Но что, если я не сделаю 'у меня есть свойство, и я назначаю выделенный объект мгновенной переменной.Мне все еще нужно выпустить?(3-я строка, второй блок кода)

@property (nonatomic, retain) MyObject *myObject;

MyObject *obj = [[MyObject alloc] init];
self.myObject = obj;
[obj release];

MyObject *myObject;

MyObject *obj = [[MyObject alloc] init];
myObject = obj;
[obj release];

ПОЖАЛУЙСТА, прочитайте полную информацию, прежде чем отмечать как дубликат

Ответы [ 5 ]

1 голос
/ 18 ноября 2010

Я знаю, что при установке сохраненного свойства для выделенного объекта он увеличивает счетчик сохранения объекта, поэтому мне нужно его освободить (3-я строка, первый блок кода)

Нет, ты этого не знаешь.Например,

foo = [[NSString alloc] initWithString: @"foo"];
[self setMyProperty: foo];

не будет увеличивать счет удержания, который начнется с INT_MAX и останется там.Однако это все детали реализации и не следует думать о .Вы действительно должны думать о владении и о том, когда вы хотите отказаться от владения.

В вашем первом блоке кода переменная obj выйдет из области видимости после выхода из блока, в котором она находится.Причина, по которой вам нужно отправить release, не имеет ничего общего с тем фактом, что вы присвоили его свойству, а также с тем фактом, что вы больше не заинтересованы в объекте, которым владеете (потому что указатель наэто собирается выйти за рамки).Кстати, «вы» мы подразумеваем область, в которой существует указатель.

Во втором случае вы назначаете объект переменным экземпляра.Переменные экземпляра живут до тех пор, пока объект они являются переменной экземпляра.Таким образом, вы должны владеть им до тех пор, пока объект не будет освобожден или переменная экземпляра не будет изменена, чтобы указывать на другой объект.

0 голосов
/ 18 ноября 2010

Расширение ответа @ PeyloW (который на 100% правильный и не должен был быть опущен) ...

Существуют особые обстоятельства, которые приводят к нежелательному использованию средств доступа в -init и -dealloc.(В первую очередь наблюдение за значением ключа, но также переопределенные методы доступа, которые могут иметь последствия / побочные эффекты, которые не подходят для частично инициализированного или частично освобожденного объекта)

//@property (nonatomic, retain) MyObject * myObject;

- (id) init {
  self = [super init];
  if (self) {
    myObject = [[MyObject alloc] init];
  }
  return self;
}

- (void) dealloc {
  [myObject release];
  [super dealloc];
}

И затем везде, где бы вы ни использовали [self setMyObject:] и [self myObject] (или self.myObject, если вы так катаетесь)

0 голосов
/ 18 ноября 2010

Во втором примере вы можете удалить избыточную переменную obj, и она будет выглядеть так:

MyObject *myObject; // declared as instance variable

//---//

myObject = [[MyObject alloc] init];
[myObject release];

Вы можете сразу увидеть, что myObject немедленно освобожден, потому что вы уравновесили alloc с release.

При непосредственном назначении переменных экземпляра вы:

  1. Как правило, не нужно использовать временные / промежуточные / вспомогательные переменные, особенно для простых случаев, подобных описанным выше.
  2. Не отпускайте его после назначения.
  3. Как правило, убедитесь, что переменная экземпляра не выпущена автоматически (например, не используйте методы класса удобства, такие как stringWithFormat:, и вместо этого используйте alloc + initWithFormat:, или, если вы используете удобный метод класса, убедитесь, что вы явно retain).
  4. Как и в случае свойств, убедитесь, что вы release указали его в методе dealloc вашего класса.
0 голосов
/ 18 ноября 2010

Я предполагаю, что в обоих ваших примерах строка, стоящая отдельно, является свойством и переменной экземпляра, как определено в интерфейсе класса.И что другой код выполняется из некоторого метода в том же классе.

Давайте посмотрим, что произойдет:

@property (nonatomic, retain) MyObject *myObject;

MyObject *obj = [[MyObject alloc] init];  // Retain count = 1
self.myObject = obj;         // Retain count +1 (2), because property is defined
                             // as retain.
[obj release];               // Retain count -1

В этом примере все работает как надо.Давайте посмотрим на второй:

MyObject *myObject;

MyObject *obj = [[MyObject alloc] init];  // Retain count = 1
myObject = obj;              // Retain count still 1. Assigns never changes
                             // retain counts.
[obj release];               // Retain count -1 (0), object is now deallocated.
                             // Any access to it though obj or myObject WILL
                             // cause a crash.

Вы можете на самом деле кодировать Objective-C и считать его почти на 100% собранным мусором, вам просто нужно доверять пулам автоматического выпуска.Всякий раз, когда вы выделяете объект, вы также должны немедленно передать его в пул автоматического выпуска.Таким образом, вам нужно беспокоиться только о том, чтобы сохранить то, что вы хотите выжить после окончания текущего метода.

Ваш первый пример может быть:

@property (nonatomic, retain) MyObject *myObject;

MyObject *obj = [[[MyObject alloc] init] autorelease];
self.myObject = obj;        // Implicitly retain through property

А ваш второй будет:

MyObject *myObject;

MyObject *obj = [[[MyObject alloc] init] autorelease];
myObject = [obj retain];    // Explicitly retained to survive end of method

Как видите, простое добавление autorelease при выделении новых объектов и последовательное использование свойств уменьшит управление памятью до простого освобождения переменных экземпляра в методе dealloc.

0 голосов
/ 18 ноября 2010

В вашем втором примере obj и myObject были освобождены после того, как вы позвонили -release, так как счетчик удерживания перешел с 1 на ноль. В первом примере, поскольку у вашего @property есть «retain», счетчик сохранений изменяется с 1 на 2, а затем возвращается к 1, когда вы его отпускаете, поэтому он не освобождается.

Короче говоря, вы должны , а не освобождать объекты, которые вы непосредственно назначаете для иваров, кроме как в рамках вашего метода -dealloc или до назначения чего-то еще тому же ивару.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...