Цель C: возвращение объектов из методов - PullRequest
1 голос
/ 29 сентября 2011

Я учусь программировать и начинаю с Objective C. Я пытаюсь точно понять, что происходит, когда объект выделяется из метода.

-(Fraction *) add: (Fraction *) f
{   //'result' will store the result of the addition

Fraction *result = [[Fraction alloc]init];

result.numerator = (numerator*f.denominator + denominator*f.numerator);
result.denominator = denominator*f.denominator;

[result reduce];
return result;
}

Я понимаю, что могу создать объект для сохранения результата в случае его возвращения,

tempStorageObject = [aFraction add: bFraction];

и что я несу ответственность за его освобождение, но что происходит, когда я его не храню, как в:

[aFraction add: bFraction];
NSLog(@"%i/%i", result.numerator, result.denominator); //result object not declared in main

Мне сказали, что у меня есть необъявленный идентификатор. Я понимаю, но что именно происходит с «результатом» после использования моего метода «добавить». Куда это идет? Разве я не должен иметь доступ к его переменным, так как он был создан и возвращен в методе? Очевидно, нет, но я не понимаю, почему. Я попытался перечитать мою книгу и найти этот форум, но не могу найти четкого ответа. Благодарю. (Первый пост)

Ответы [ 3 ]

3 голосов
/ 29 сентября 2011

Четыре разные вещи:

  1. Свойства
  2. Локальные переменные
  3. Возвращаемые значения функции
  4. Куча хранилища

«Я понял, но что именно происходит с« результатом »после использования моего метода« добавить ». Куда это идет?»

Это локальная переменная. Это ушло.

«Разве я не смогу получить доступ к его переменным»

Видя ваш комментарий, похоже, что вы имеете в виду доступ через точечную запись. Нет, точечная запись предназначена для свойств.

"с момента его создания"

Точечная запись не дает вам доступа к локальным переменным.

"а вернули в метод?"

Точечная запись не дает вам доступа к возвращаемым значениям функции.

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

  1. Когда вы вызываете alloc, объект создается в куче.

  2. Когда вы присваиваете результат результату, теперь результат имеет тот же объект.

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

4а. Когда вы присваиваете результат функции для tempStorageObject, другой локальной переменной (я полагаю), результат функции исчезает. Он существовал только временно, чтобы передать значение изнутри функции наружу. TempStorageObject теперь содержит объект, и объект все еще существует в куче.

4b. Вместо этого, если вы не назначаете результат функции чему-либо, результат функции все равно уходит. Но объект все еще существует в куче. У тебя проблемы. У вас есть объект в куче, но вы не можете напрямую ссылаться на него (если вы не умеете угадывать его адрес). Не имея возможности ссылаться на него, вы не сможете получить его из кучи, что будет серьезной проблемой, если вы будете делать такие вещи снова и снова. Куча начнет заполняться объектами, от которых вы не сможете избавиться, и у вас не хватит памяти. Это то, что называется утечкой.

В этом случае правильно сделать return [result autorelease]. Когда вы вызываете [something autorelease], он добавляет «что-то» в «пул автоматического выпуска», а затем возвращает то же самое.

  1. Вы вызываете alloc и создаете объект в куче. Его счет отсчета начинается с 1.

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

  3. [result autorelease]. У результата есть объект, он находится в пуле автоматического выпуска и находится в куче.

  4. верните это. результат пропал, возвращаемое значение имеет объект, оно находится в пуле автоматического выпуска и находится в куче.

5a. Присвойте возвращаемое значение tempStorageObject. Возвращаемое значение пропало, объект tempStorageObject имеет объект, он находится в пуле автоматического выпуска и находится в куче.

6а. Вы покидаете область действия tempStorageObject. объект tempStorage исчез. Объект находится в пуле авто-релиза и в куче.

5б. Вы не назначаете результат функции ни для чего. Результат функции пропал. Объект находится в пуле авто-релиза и в куче.

7AB. Авто-релиз бассейн слит. Обычно это делается из кода в главном цикле выполнения, предоставляемого системной библиотекой, но вы можете сделать это самостоятельно, если знаете как. Все объекты в пуле автоматического выпуска, в том числе тот, на который мы обращаем внимание, отправляются в виде сообщения о выпуске. Число сохраняемых объектов увеличивается до 0.

8AB. Со счетом сохранения 0 объект удаляется из кучи. Объект находится в пуле автоматического выпуска.

9ab. Второе, что делает сток, это удаляет все объекты из бассейна. Теперь объект больше нигде не существует.

1 голос
/ 29 сентября 2011

Область применения alloc является глобальной: после выделения объекта в памяти остается место для него, и эта память остается распределенной до тех пор, пока счетчик выпусков не достигнет нуля (или приложение не будет закрыто).До тех пор объект все еще будет существовать.

Область действия переменной намного короче.В вашем примере «результат» выходит из области действия прямо в конце метода «добавить».Но эта переменная - просто имя, ссылка на объект.Поэтому тот, кто вызывает add, должен обязательно что-то сделать с возвращенным объектом.В противном случае больше нет переменной, ссылающейся на объект, и поэтому он не может быть освобожден.

1 голос
/ 29 сентября 2011

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

Программирование управления памятью

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