Как управляется память для объекта, который создан, но не назначен ни одному указателю?

Это может быть глупый вопрос, но он продолжает беспокоить меня.

Скажем, если у нас есть метод, который принимает NSString объект в качестве параметра и что-то делает с NSString объект,

- (void)someMethod:(NSString *)str
{
    //do something with str
}

Рассмотрим этот код

[someObject someMethod:[[NSString alloc] initWithFormat:@"Hello World!"]];

поскольку alloc был использован при создании строки в качестве параметра someMethod, он должен быть сбалансирован release не имеет значения явно в среде до ARC или неявно в рамках ARC. Но, похоже, мы никак не можем получить указатель на строку, так как мы никогда не назначали ее ни одному указателю.

Итак, мой вопрос, во-первых, запрещен ли этот способ передачи параметров при написании кода на объекте c? Если нет, то как объекты, созданные таким образом, освобождаются? И, наконец, приводит ли этот код к утечке памяти?


Просто для записи я так понимаю вышеприведенный код написан

NSString *string = [[NSString alloc] initWithFormat:@"Hello World!"];
[someObject someMethod:string];
// [string release]; depending on ARC or non-ARC

3 ответа

Решение

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

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

При MRR ваш фрагмент будет утечкой; правильный способ избежать этого также отправить autorelease:

[someObject someMethod:[[[NSString alloc] initWithFormat:@"Hello World!"] autorelease]];

или использовать ваш последний фрагмент (поместив строку во временную переменную и освободив позже).

Как слегка эзотерический вариант, ваш метод может объявить, что он владеет аргументом, используя ns_consumed атрибут:

- (void)someMethod:(NSString *) __attribute__((ns_consumed)) str;

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

Итак, мой вопрос, во-первых, запрещен ли этот способ передачи параметров при написании кода на объекте c?

Нет, это совершенно законно.

Если нет, то как объекты, созданные таким образом, освобождаются?

ARC позаботится об этом за вас. Если вы делаете свой собственный подсчет ссылок, то вы можете добавить его в пул автоматического выпуска, прежде чем он выйдет из области видимости:

[someObject someMethod:
  [[[NSString alloc] initWithFormat:@"Hello World!"] autorelease]];
                                                     ^^^^^^^^^^^

И, наконец, приводит ли этот код к утечке памяти?

Не в ARC. В MRC вам нужно добавить -autorelease,

Статический анализатор также указал бы на эту утечку.

Нет причин не писать код, поскольку вы просите о рассмотрении… ничего запрещенного ни в малейшей степени. Эти объекты освобождаются так же, как и любой другой объект. Отсутствие переменной для хранения указателя на верхнем уровне не имеет значения, поскольку среда выполнения Objective C знает об объекте.