Объявить объект внутри или снаружи цикла?

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

Один из методов в этом отношении, который часто встречается в библиотеках, - это функция Delete:

template< class T > void Delete( T*& pointer )
{
    delete pointer;
    pointer = NULL;
}

Это предотвращает случайный доступ к недопустимой памяти.

Обратите внимание, что вполне нормально называть delete NULL;.

55
задан Yuval Adam 18 December 2008 в 13:03
поделиться

14 ответов

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

47
ответ дан Dave Markle 7 November 2019 в 17:22
поделиться

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

, Если объект является большим или сложным, абсолютно объявите его вне цикла. Иначе люди, говорящие Вам не преждевременно оптимизировать, правы.

-1
ответ дан Max 7 November 2019 в 17:22
поделиться

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

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

0
ответ дан Jack Ryan 7 November 2019 в 17:22
поделиться

Как кто-то, кто поддерживает больше кода, чем код записей.

Версия 1 очень предпочтена - сохраняющий объем, максимально локальный, важно для понимания. Его также легче осуществить рефакторинг этот вид кода.

, Как обсуждено выше - я сомневаюсь, что это имело бы любое значение в эффективности. На самом деле я утверждал бы, что, если объем более локален, компилятор может быть в состоянии сделать больше с ним!

0
ответ дан Fortyrunner 7 November 2019 в 17:22
поделиться

В обоих случаях информация о типе для объекта o определяется во время компиляции. Во втором экземпляре o замечен как являющийся глобальным к для цикла и прежде всего, умный компилятор Java знает, что o должен будет быть доступным столько, сколько цикл длится и следовательно оптимизирует код таким способом который там привычка быть любым respecification типа o в каждом повторении. Следовательно, в обоих случаях, спецификация типа o будет сделана однажды, что означает, что единственное различие в производительности было бы в пределах o. Очевидно, более узкий объем всегда улучшает производительность, поэтому для ответа на вопрос: нет, нет никакой потери производительности для первого надреза кода; на самом деле этот надрез кода более оптимизирован, чем второе.

Во втором надрезе, o дают ненужный объем, который, помимо того, чтобы быть проблемой производительности, может быть также проблемой безопасности.

0
ответ дан Lonzo 7 November 2019 в 17:22
поделиться

Добираться в основе этого вопроса... [Обратите внимание, что реализации не-JVM могут сделать вещи по-другому, если позволено JLS...]

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

Все локальные переменные выделяются на стеке этапа выполнения в 4-байтовых слотах. удваивается и longs требуют двух слотов; другие примитивы и указатели берут тот. (Даже булевские переменные берут весь слот)

, зафиксированный размер стека этапа выполнения А должен быть создан для каждого вызова метода. Этот размер определяется максимальной локальной переменной "слоты", необходимые в любом данном пятне в методе.

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

В обоих случаях, тот же байт-код будет сгенерирован, обновляя тот же слот в стеке этапа выполнения.

, Другими словами, никакая потеря производительности вообще.

ОДНАКО в зависимости от остальной части кода в методе, "объявление вне цикла" версия могло бы на самом деле потребовать большего выделения стека этапа выполнения. Например, сравните

for (...) { Object o = ... }
for (...) { Object o = ... }

с [1 110]

Object o;
for (...) {  /* loop 1 */ }
for (...) { Object x =...; }

В первом примере, оба цикла требуют того же выделения стека этапа выполнения.

Во втором примере, потому что "o" живет мимо цикла, "x" требует дополнительного слота стека этапа выполнения.

Hope это помогает, - Scott

1
ответ дан Scott Stanchfield 7 November 2019 в 17:22
поделиться

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

1
ответ дан Will Mc 7 November 2019 в 17:22
поделиться

Они имеют различную семантику. Который более значим?

Многократное использование объекта по "причинам производительности" является часто неправильным.

вопрос - то, что "означает" объект? ПОЧЕМУ Вы создаете его? Что это представляет? Объекты должны быть параллельными реальным вещам. Вещи создаются, претерпевают изменения состояния и сообщают о своих состояниях по причинам.

, Каковы те причины? Как делает Вашу объектную модель и отражают те причины?

1
ответ дан S.Lott 7 November 2019 в 17:22
поделиться

Я должен признать, что не знаю Java. Но действительно ли эти два эквивалентны? Действительно ли объектное время жизни является тем же? В первом примере я принимаю (не знание Java), что o будет сразу иметь право на сборку "мусора", цикл завершается.

, Но во втором примере, конечно, o не будет иметь право на сборку "мусора", пока из внешнего объема (не показанный) не выйдут?

4
ответ дан Paul Mitchell 7 November 2019 в 17:22
поделиться

Нет никакой потери производительности для объявления Объекта o в цикле. Компилятор генерирует очень похожий байт-код и делает корректную оптимизацию.

Видят, что Миф о статье - Определяющий переменные цикла в цикле плох для производительности для подобного примера.

10
ответ дан Marco Tolk 7 November 2019 в 17:22
поделиться

Можно демонтировать код с javap-c и проверить то, что на самом деле испускает компилятор. На моей установке (Java 1.5/mac скомпилированных с затмением), байт-код для цикла идентичен.

7
ответ дан Rolf Rander 7 November 2019 в 17:22
поделиться

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

На самом деле, некоторые люди могли бы думать, что, если компилятор является немым, второй отрывок лучше с точки зрения производительности. Это - то, что некоторый преподаватель сказал мне в колледже, и я смеялся над ним для этого предложения! В основном компиляторы выделяют память на стеке для локальных переменных метода только однажды в начале метода (путем корректировки указателя вершины стека) и выпускают его в конце метода (снова путем корректировки указателя вершины стека, предположения, что это не C++, или это не имеет никаких деструкторов, которые назовут). Таким образом, все стековые локальные переменные в методе выделяются сразу, неважно, где они объявляются и какого количества памяти они требуют. На самом деле, если компилятор является немым, нет никакого различия в терминах производительности, но если это достаточно умно, первый код может на самом деле быть лучше, поскольку это поможет компилятору понять объем и время жизни переменной! Между прочим, если это действительно умно, там не должен нет абсолютно никакая разница в производительности, поскольку это выводит фактический объем.

Конструкция объекта с помощью new полностью отличается от просто объявления его, конечно.

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

5
ответ дан Mehrdad Afshari 7 November 2019 в 17:22
поделиться

Преждевременно не оптимизировать. Лучше, чем любой из них:

for(Object o : someList) {
    o.doSomething();
}

, потому что это устраняет шаблон и разъясняет намерение.

, Если Вы не работаете над встроенными системами, в этом случае все ставки выключены. Иначе не пытайтесь перехитрить JVM.

4
ответ дан SamBeran 7 November 2019 в 17:22
поделиться

Для заключения в кавычки Knuth, который может заключать Hoare в кавычки:

Преждевременная оптимизация является корнем всего зла.

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

Сравнивают это с количеством ошибок, Вы, вероятно, предотвратите правильно определяющим объем свою переменную с помощью объявления в цикле...

16
ответ дан Dan Vinton 7 November 2019 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: