Ошибки в книге "Learn Objective-C на Mac" или плохое понимание памяти? - PullRequest
2 голосов
/ 11 сентября 2011

В книге «Изучите Objective-C на Mac» вы можете найти следующий код, который я считаю ошибочным:


«Вот еще одна попытка написания setEngine:

- (void) setEngine: (Engine *) newEngine  
{  
      [engine release];  
      engine = [newEngine retain];  
}

... обдумайте этот случай:

Engine *engine = [Engine new]; // count: 1  
Car *car1 = [Car new];  
Car *car2 = [Car new]; 

[car1 setEngine: engine]; // count: 2 
[engine release]; // count 1 

[car2 setEngine: [car1 engine]]; //Ops...

Почему это проблема?Вот что происходит.[car engine] возвращает указатель на engine, у которого счет сохранения равен 1. Первая строка setEngine - это [engine release], что делает счет сохранения 0, когда объект освобождается .... "


Однако, после прочтения этого параграфа на стр. 166. Интересно, какое отношение имеет внутренняя ссылка на двигатель в car2 к двигателю в car1. Это две разные ссылки и к тому времени "[car2 setEngine: [car1 engine]]"is invoke, двигатель в car2 не был инициализирован и не имеет никакого отношения к оставшемуся двигателю, о котором говорит автор. Таким образом," [выпуск двигателя] "не уменьшит значение счетчика до 0 для двигателя car1.это ошибка или я ужасно ошибаюсь?

((Я хотел бы обсудить этот конкретный код, а не правильный способ реализации установщика))

Ответы [ 2 ]

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

Какой класс setEngine: in?Я предполагаю, что это в машине.И у этой машины есть переменная экземпляра типа Engine *, называемая engine.Это НЕ тот же указатель Engine *, что и во втором фрагменте кода (который должен быть классом контроллера с собственными переменными экземпляра).

Во-первых, модуль IS инициализирован.[Engine new] совпадает (для всех практических целей) с [[Engine alloc] init].

Итак, у вас есть два объекта Car и 1 объект Engine.Вы устанавливаете переменную экземпляра engine в car1 так, чтобы она указывала на объект engine.Затем отпустите оригинальный указатель.Хорошо.Затем вы также назначаете его на car2.Если у car2 был другой двигатель, он освобождается и назначается новый.Если у него не был назначен движок, сообщение об освобождении отправляется на ноль (что нормально), и оно также назначается.

Все нормально.

PS - в то время как Цель-C имеет конструкцию new, ее использование, как правило, плохая идея, потому что она скрывает двухэтапный шаблон создания, который является нормой для фреймворков Apple.Используйте alloc & init.

0 голосов
/ 11 сентября 2011

Сеттер не прав. Это может быть:

- (void) setEngine: (Engine *) newEngine  
{
  if(newEngine != engine)
  {
   [engine release];  
   engine = [newEngine retain]; 
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...