Почему NSSet objectEnumerator увеличивает счетчик удержания?

После получения objectEnumerator в следующем коде счетчик сохранения set1 становится равным 3. Я был удивлен, увидев это, потому что не ожидал, что он изменится. Я искал документация и не могу найти, где объясняется этот эффект.

Я предполагаю, что дополнительные удержания, вероятно, настроены на автоматическое освобождение логикой перечисления Какао и на самом деле не будут иметь никакого эффекта в текущем цикле событий. Логика objectEnumerator может нуждаться в ссылке на set1, но я хотел бы знать, почему они были созданы. Вот причина: если я предполагаю, что set1 сохранил нулевой счетчик после выпуска в коде, я мог бы попытаться повторно использовать его в другом новом наборе. Разве это не вызовет проблем, поскольку set1 теперь указывает на совершенно другой объект / адрес?

Для «бонусных» баллов, есть ли способ перечислить пул автозапуска и посмотреть, что он на самом деле содержит? TIA

#import <Foundation/NSObject.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>

#import <stdio.h>;

// macro to create an integer number:
#define INTOBJ(v) [NSNumber numberWithInt: v]

int main (int argc, char *argv[])
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    //Make set
    NSMutableSet *set1 = [[NSMutableSet alloc] initWithObjects:
        INTOBJ(1), INTOBJ(2), INTOBJ(5), INTOBJ(10), nil];

    printf("set1 #%lu\n", [set1 retainCount]);

    //Get enumerator of the set. This is where the retain count goes to 3:
    NSEnumerator *setEnum = [set1 objectEnumerator];
    printf("setEnum #%lu\n", [setEnum retainCount]);
    printf("set1 #%lu\n", [set1 retainCount]);

    //Iterate through the collection:
    printf("[");

    NSNumber *element;
    while ((element = [setEnum nextObject]) != nil)
        //do some this with item. printf is just for debugging:
        printf(" %i ", [element intValue]);

    printf("]\n");
    printf("set1 #%lu\n", [set1 retainCount]);

    [set1 release];
    printf("set1 after release #%lu\n", [set1 retainCount]);

    //More logic could go here reusing variable set1 since I assumed retain count = 0

    [pool release];

    return 0;
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
2 178
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Повторное использование set1 после выпуска не вызовет проблем, потому что счетчик удержания относится к объекту, на который ссылается переменная set1, а не к самой переменной.

Ответ принят как подходящий

Обычно не стоит полагаться на сохраняемое количество объектов, поскольку это внутренняя деталь фреймворка. Вместо этого убедитесь, что ваш код соответствует принципам управления памятью, в частности, убедитесь, что сохранение / новое / копирование и выпуск / автозапуск сбалансированы.

Я один из немытых разработчиков .NET, попадающих в Obj-C, поэтому мне не хватает управляемого GC. Благодаря таким людям, как вы, я научился обращаться с счетчиками удержания. В .NET переменные «освобождаются», когда выходят за пределы области видимости, и на них не ссылаются. Что вы думаете об этом сообщении: kickingbear.com/blog/?p=17

Sixto Saez 01.12.2008 23:22

Я могу понять, почему вы определили эти макросы, но они меня до чертиков запутали при проверке кода ;-)

user23743 02.12.2008 02:18

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

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

Другие вопросы по теме