Задача C проблема с памятью - PullRequest
1 голос
/ 26 июля 2010

У меня есть 2 сценария, и я хочу знать, какой путь правильный и лучший?


-(Employee*) getCustomEmployee{

  Employee *emp = [[Employee alloc]init]; // no autorelease here
  //do something with emp

  return emp;
}

-(void) process{

   Employee *emp = [self getCustomEmployee];
   //do something with emp

   [emp release]; //release emp object here

}

-(Employee*) getCustomEmployee{

  Employee *emp = [[[Employee alloc]init]autorelease]; //NOTE: autorelease here 
 //do something with emp

  return emp;
}

-(void) process{

   NSAutoreleasePool *pool = [[NSAutoReleasePool allc]init];

   Employee *emp = [self getCustomEmployee];
   //do something with emp

   [pool release];

}

Ответы [ 7 ]

2 голосов
/ 26 июля 2010

Если вы стремитесь следовать соглашению Какао, у вас должен быть четкий ответ на ваш вопрос в этой статье

2 голосов
/ 26 июля 2010

2-й - лучшая практика, но все же неверная Вы кодируете геттер, который не должен создавать память. Вместо этого он должен вернуть ссылку на уже созданную память. Было бы лучше переименовать его в заводской метод «customEmployee» и использовать автоматический выпуск, поскольку это соглашение об именах, поощряемое Apple и встречающееся в других вызовах API. Вы также можете создать createCustomEmployee, который не выпускает автоматически. Здесь важно соглашение об именах.

1 голос
/ 26 июля 2010

Если оставить в стороне тот факт, что вы не должны ставить перед этими методами префикс 'get' в соответствии с соглашениями об именах Apple, вторая версия является более правильной, поскольку она соответствует правилам управления памятью Apple.

Вы можетесделайте первый пример лучше, добавив префикс имени метода 'new', например newCustomEmployee.Тем не менее, использование new является своего рода устаревшим.

1 голос
/ 26 июля 2010

Я не думаю, что AutoreleasePool требуется во втором.Я уверен, что есть один по умолчанию.Так что, если ваш метод процесса не очень интенсивный, пул не нужен.

Я бы сказал, что авто-релиз - это путь.

Представьте, что вам нужно вызвать getCustomEmployee методов из разных мест в вашем коде.Каждый раз, когда вы будете вызывать этот метод, вам придется помнить об освобождении сотрудника.

0 голосов
/ 26 июля 2010

Второе лучше.

Из Руководства по программированию управления памятью :

  • Вы владеете любым создаваемым вами объектом.
  • Вы «создаете» объект, используя метод, имя которого начинается с «alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy).

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

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

- (Employee*) getCustomEmployee {
   Employee *emp = [[[Employee alloc] init] autorelease];
   // do something with emp
   return emp;
}

- (void) process {
  Employee *emp = [self getCustomEmployee];
  // do something with emp
}

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

В этом случае, если сотрудник может быть разделен между несколькими вызывающими, тогда вы можете рассмотреть ленивую инициализацию.В следующем коде предполагается, что у вас есть переменная экземпляра (ivar в языке target-c) с именем _employee.

- (Employee*) getCustomEmployee {
   @synchronized(self)
      if (!_employee) {
         _employee = [[Employee alloc] init];
      }
   }
   return _employee;
}

- (void) dealloc {
   [_employee release];
}

- (void) process {
  Employee *emp = [self getCustomEmployee];
  // do something with emp
}

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

0 голосов
/ 26 июля 2010

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

  • Если вы возвращаете объект, который должен освободить вызывающий объект, вам следует назвать свою подпрограмму createCustomEmployee вместо getCustomEmployee, чтобы следовать соглашениям о присвоении имен Какао. (Подпрограммы с create или alloc в имени возвращают объект, который должен быть освобожден).
0 голосов
/ 26 июля 2010

Обычно второй - в Objective-C вы обычно возвращаете автоматически выпущенные объекты из метода, если это не метод init или copy.

...