В чем разница между retain/release и autorelease в управлении памятью Objective-C?

Ответ

Это методы ручного управления памятью (MRC) в Objective-C.

retain / release

  • retain — увеличивает счетчик ссылок (retain count) объекта на 1.
  • release — уменьшает счетчик ссылок на 1. Когда счетчик достигает 0, память объекта немедленно освобождается.
  • Прямое и предсказуемое управление временем жизни.
// MRC (Manual Reference Counting)
NSObject *obj = [[NSObject alloc] init]; // retainCount = 1
[obj retain]; // retainCount = 2
[obj release]; // retainCount = 1
[obj release]; // retainCount = 0 -> объект деаллоцирован

autorelease

  • autorelease — добавляет объект в текущий autoreleasepool, откладывая отправку release.
  • release будет вызван автоматически, когда пул будет дренирован (обычно в конце цикла runloop).
  • Удобно для возврата временных объектов из методов.
- (NSString *)generateName {
    // Объект будет освобожден позже, когда дренируется autoreleasepool
    return [[[NSString alloc] initWithFormat:@"Name_%d", 1] autorelease];
}

Практическое значение: С появлением ARC (Automatic Reference Counting) необходимость вручную вызывать эти методы отпала. Однако понимание важно для работы с legacy-кодом, Core Foundation (где используется CFRetain/CFRelease) и для низкоуровневой оптимизации с использованием @autoreleasepool.

Ответ 18+ 🔞

А, Objective-C, ёпта, старый добрый ручной разбор полётов с памятью! Прямо как в девяностых, блядь, когда каждый байт на счету был и ты сам решал, кому жить, а кому — в утиль. Сейчас, конечно, всё за тебя ARC делает, но знать, как эта штука работает изнутри — это как понимать, откуда у машины ноги растут, а не просто газу давить.

Ну, слушай сюда, про эту вашу ручную возню.

retain / release — это типа ручное переключение передач, блядь.

  • retain — это ты кричишь объекту: «Стой, сука, не уходи! Я тебя ещё поюзать хочу!». Счётчик ссылок плюсуется.
  • release — это ты говоришь: «Всё, свободен, пошёл нахуй». Счётчик минусуется. Как только он в ноль — объект тут же, на месте, отправляется к праотцам. Никаких отсрочек, мгновенная казнь, пиздец.
// Ручное управление, мать его
NSObject *obj = [[NSObject alloc] init]; // retainCount = 1 (родился)
[obj retain]; // retainCount = 2 (кричим "стой!")
[obj release]; // retainCount = 1 (говорим "ладно, иди")
[obj release]; // retainCount = 0 -> объект деаллоцирован (окончательное "пошёл нахуй")

А теперь autorelease — это хитрая жопа, отложенный приговор.

  • Ты не убиваешь объект сразу. Ты как бы говоришь: «Знаешь что, дружок-пирожок, я тебя сейчас отпущу, но ты погуляй пока в этом нашем autoreleasepool. Как все разойдутся — тебя там и прибьют».
  • Удобно, блядь, когда из метода возвращаешь какой-нибудь временный объект. Создал, autorelease ему впендюрил, вернул — и не паришься, что он сдохнет раньше, чем вызывающий код его увидит.
- (NSString *)generateName {
    // Сделал имя, сука
    NSString *name = [[NSString alloc] initWithFormat:@"Name_%d", 1]; // retainCount = 1
    // А вместо того чтобы самому release делать, скинул в автопул. Пусть там разбираются.
    return [name autorelease];
    // Когда текущий autoreleasepool дренится (опустошается), name получит свой release.
}

А нахуя это сейчас надо, если есть ARC?

А вот, блядь, практическое значение, чтоб ты знал:

  1. Легаси-код. Наследие, ёпта. Тонны старого говнокода, который ещё жив и его надо поддерживать. Там этого ручного управления — овердохуища.
  2. Core Foundation. Эта библиотека, она живёт по своим правилам, там CFRetain/CFRelease. Чтобы мосты между мирами (__bridge, CFBridgingRetain) строить — надо понимать, кто за кого отвечает.
  3. Низкоуровневая оптимизация. Иногда, чтобы не жрать память как не в себя, ты вручную @autoreleasepool {} в цикл засунешь, чтобы промежуточный хлам почаще чистился. А чтобы понять, как он чистится — надо знать про autorelease.

Короче, знание этой ручной темы — это как умение ездить на механике. На автомате, конечно, проще, но когда надо вручную в горку тронуться или с буксом вылезти — без этих навыков ты просто обосрёшься на месте. Вот и вся философия, блядь.