Использовать автовыпуск прежде, чем добавить объекты к набору?

Я задал вопрос по этому поводу, и меня отправили на этот пост с сообщением:

На этот вопрос уже есть ответ:

«Примечание: неопределенная переменная», «Уведомление: неопределенный индекс» и «Уведомление: неопределенное смещение» с использованием PHP

Я делюсь своим вопросом и решением здесь:

Это ошибка:

enter image description here

Строка 154 - это проблема. Это то, что у меня есть в строке 154:

153    foreach($cities as $key => $city){
154        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

Я думаю, проблема в том, что я пишу условия для переменной $city, которая является не ключом, а значением в $key => $city. Во-первых, не могли бы вы подтвердить, является ли это причиной предупреждения? Во-вторых, если это проблема, почему я не могу написать условие, основанное на значении? Должно ли это быть с ключом, который мне нужен для записи условия?

ОБНОВЛЕНИЕ 1: Проблема в том, что при выполнении $citiesCounterArray[$key] иногда $key соответствует ключу, который не существует в $citiesCounterArray массив, но это не всегда так, основываясь на данных моего цикла. Мне нужно установить условие, чтобы, если в массиве было $key, запустить код, в противном случае пропустить его.

ОБНОВЛЕНИЕ 2: Вот как я это исправил, используя array_key_exists():

foreach($cities as $key => $city){
    if(array_key_exists($key, $citiesCounterArray)){
        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

5
задан Philippe Leybaert 18 July 2009 в 15:59
поделиться

6 ответов

Оба верны и будут работать так, как вы от них ожидаете.

Лично я предпочитаю использовать последний метод, но только потому, что мне нравится четко указывать, когда объекты будут освобождены. Освобождая объект автоматически, мы всего лишь говорим: «Этот объект будет выпущен в произвольный момент в будущем». Это означает, что вы можете поместить автоматически выпущенный объект в массив, уничтожить массив, и объект может (вероятно) все еще существовать.

При использовании последнего метода объект будет немедленно уничтожен вместе с массивом (при условии, что ничего другого не поступило. вместе и пока сохранил его). Если я нахожусь в среде с ограниченным объемом памяти (скажем, iPhone), где мне нужно быть осторожным с тем, сколько памяти я использую, я буду использовать последний метод, просто чтобы не У меня где-то в NSAutoreleasePool хранится так много объектов. Если использование памяти вас не беспокоит (и обычно меня тоже), то любой метод полностью приемлем.

7
ответ дан 18 December 2019 в 07:10
поделиться

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

Итак, с одним объектом A и B более или менее одинаковы, но определенно не используйте A в сценариях с большим количеством объектов для добавления в массив.

В разных ситуациях автоматическое освобождение может задерживать и накапливать освобождение многих объектов в конце потока. Это может быть неоптимально. Позаботьтесь о том, чтобы автоспуск часто происходил без явного вмешательства. Например, многие геттеры реализованы следующим образом:

return [[myObject retain] autorelease];

поэтому всякий раз, когда вы вызываете геттер, вы добавляете объект в пул автозапуска.

3
ответ дан 18 December 2019 в 07:10
поделиться

ИМХО, какой из способов «правильный» - это вопрос предпочтений. Я согласен с теми, кто выступает за отказ от использования автозапуска , но я предпочитаю использовать автозапуск , если только нет веских причин не делать этого. Я перечислю свои причины, и вы сможете решить, подходят ли они вашему стилю программирования.

Как отметил Чак, существует легенда о том, что использование пулов с автоматическим выпуском связано с некоторыми накладными расходами. Это далеко от истины, и это результат бесчисленных часов, потраченных на Shark.app, чтобы выжать из кода последнюю каплю производительности. Попытка оптимизировать для этого находится глубоко в зоне «преждевременной оптимизации». Если и только если Shark.app предоставляет вам достоверные данные, что это может быть проблемой, если вы даже подумайте о том, чтобы заглянуть в него.

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

Однако иногда вам нужно избавиться от них временные объекты раньше, чем позже. Например, вам нужно обработать огромный файл размером в несколько мегабайт или десятки тысяч строк из базы данных. Когда это произойдет, вам нужно будет разместить NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; в правильно выбранную точку, а затем [выпуск пула]; в дно. Это почти всегда происходит при некоторой «пакетной обработке цикла», поэтому обычно это происходит в начале и в конце некоторого критического цикла. Опять же, это должно быть основано на доказательствах, а не на догадках. Инструмент ObjectAlloc из Instrument.app - это то, что вы используете для поиска этих проблемных мест.

Однако основная причина, по которой я предпочитаю автоматический выпуск выпуску , заключается в том, что он много легче писать программы без утечек. Короче говоря, если вы выберете вариант выпуск , вам необходимо гарантировать , что релиз в конечном итоге будет отправлен на obj при всех обстоятельствах. Хотя кажется, что это может быть просто, на самом деле это удивительно сложно сделать на практике. Возьмем, к примеру, ваш пример:

   // array is an instance of NSMutableArray
   MyClass *obj = [[MyClass alloc] init];
   [array addObject:obj];
   // Assume a few more lines of work....
   [obj release];

А теперь представьте, что по какой-то причине что-то где-то тонко нарушает ваше предположение о том, что массив является изменяемым, возможно, в результате использования какого-либо метода для обработки результатов, и возвращенный массив, содержащий обработанные результаты, был создан как NSArray . Когда вы отправляете addObject: в этот неизменяемый NSArray , возникает исключение, и вы никогда не отправите obj его сообщение release . Или, может быть, что-то пойдет не так где-то между obj было alloc d и требовалось позвонить в release , например, вы проверили какое-то условие, и return () сразу же по ошибке, потому что вы забыли, что этот вызов release позже должен иметь место .

Вы только что пропустили объект. И, вероятно, записался на несколько дней, чтобы выяснить, где и почему вы его сливаете. По опыту, вы потратите много часов, глядя на этот код выше, убеждаясь, что он не может быть источником утечки, потому что вы очень четко отправляете obj выпуск . Затем, через несколько дней, вы испытаете то, что можно описать только как религиозное прозрение, когда вы поймете причину проблемы.

Рассмотрим случай автозапуска :

   // array is an instance of NSMutableArray
   MyClass *obj = [[[MyClass alloc] init] autorelease];
   [array addObject:obj];
   // Assume a few more lines of work....

Теперь уже не имеет значения, что происходит, потому что практически невозможно случайно утечь obj , даже в чрезвычайно необычных или исключительных угловых случаях. 1124790]

12
ответ дан 18 December 2019 в 07:10
поделиться

Вы можете отправить сообщение autorelease в любой момент, потому что оно не выполняется до тех пор, пока цикл сообщений приложения не повторится (т. Е. Пока все ваши методы не завершат выполнение в ответ для ввода пользователем).

http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text

0
ответ дан 18 December 2019 в 07:10
поделиться

You have alloc'ed the object, then it's your job to release it at some point. Both code snippets work merely the same, correct way, with the autorelease way being the potentionally slower counterpart.

Personally speaking, I prefer the autorelease way, since it's just easier to type and almost never is a bottleneck.

0
ответ дан 18 December 2019 в 07:10
поделиться

Они оба в порядке. Некоторые люди скажут вам избегать автоспуска из-за "накладных расходов" или чего-то подобного, но правда в том, что накладных расходов практически нет. Идите вперед, сравните его и попытайтесь найти "накладные расходы". Единственная причина, по которой вы бы этого не сделали, - это ситуация с нехваткой памяти, как на iPhone. В OS X у вас практически неограниченная память, так что это не будет иметь большого значения. Просто используйте то, что вам удобнее.

0
ответ дан 18 December 2019 в 07:10
поделиться