Удалить ничего не удаляет - он просто отмечает, что память «свободна для повторного использования». До тех пор, пока некоторые другие вызовы выделения не будут зарезервированы и заполнят это пространство, у него будут старые данные. Однако, полагаясь на то, что это большой нет-нет, в основном, если вы удаляете что-то забыть об этом.
Один из методов в этом отношении, который часто встречается в библиотеках, - это функция Delete:
template< class T > void Delete( T*& pointer )
{
delete pointer;
pointer = NULL;
}
Это предотвращает случайный доступ к недопустимой памяти.
Обратите внимание, что вполне нормально называть delete NULL;
.
В сегодняшних компиляторах, нет. Я объявляю объекты в самом маленьком объеме, я могу, потому что это намного более читаемо для следующего парня.
Ответ зависит частично от того, что делает конструктор и что происходит с объектом после цикла, так как это определяет в большой степени, как код оптимизирован.
, Если объект является большим или сложным, абсолютно объявите его вне цикла. Иначе люди, говорящие Вам не преждевременно оптимизировать, правы.
Первое имеет намного больше смысла. Это сохраняет переменную в объеме, в котором это используется. и предотвращает значения, присвоенные в одном повторении, используемом в более позднем повторении, это - больше обороны.
Первый, как иногда говорят, более эффективен, но любой разумный компилятор должен быть в состоянии оптимизировать его, чтобы быть точно тем же как последним.
Как кто-то, кто поддерживает больше кода, чем код записей.
Версия 1 очень предпочтена - сохраняющий объем, максимально локальный, важно для понимания. Его также легче осуществить рефакторинг этот вид кода.
, Как обсуждено выше - я сомневаюсь, что это имело бы любое значение в эффективности. На самом деле я утверждал бы, что, если объем более локален, компилятор может быть в состоянии сделать больше с ним!
В обоих случаях информация о типе для объекта o определяется во время компиляции. Во втором экземпляре o замечен как являющийся глобальным к для цикла и прежде всего, умный компилятор Java знает, что o должен будет быть доступным столько, сколько цикл длится и следовательно оптимизирует код таким способом который там привычка быть любым respecification типа o в каждом повторении. Следовательно, в обоих случаях, спецификация типа o будет сделана однажды, что означает, что единственное различие в производительности было бы в пределах o. Очевидно, более узкий объем всегда улучшает производительность, поэтому для ответа на вопрос: нет, нет никакой потери производительности для первого надреза кода; на самом деле этот надрез кода более оптимизирован, чем второе.
Во втором надрезе, o дают ненужный объем, который, помимо того, чтобы быть проблемой производительности, может быть также проблемой безопасности.
Добираться в основе этого вопроса... [Обратите внимание, что реализации не-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
Я всегда думал, что большинство компиляторов в эти дни достаточно умно, чтобы сделать последнюю опцию. Принятие этого имеет место, я сказал бы, что первый действительно выглядит более хорошим также. Если цикл становится очень большим, нет никакой потребности посмотреть все вокруг для того, где o объявляется.
Они имеют различную семантику. Который более значим?
Многократное использование объекта по "причинам производительности" является часто неправильным.
вопрос - то, что "означает" объект? ПОЧЕМУ Вы создаете его? Что это представляет? Объекты должны быть параллельными реальным вещам. Вещи создаются, претерпевают изменения состояния и сообщают о своих состояниях по причинам.
, Каковы те причины? Как делает Вашу объектную модель и отражают те причины?
Я должен признать, что не знаю Java. Но действительно ли эти два эквивалентны? Действительно ли объектное время жизни является тем же? В первом примере я принимаю (не знание Java), что o будет сразу иметь право на сборку "мусора", цикл завершается.
, Но во втором примере, конечно, o не будет иметь право на сборку "мусора", пока из внешнего объема (не показанный) не выйдут?
Нет никакой потери производительности для объявления Объекта o в цикле. Компилятор генерирует очень похожий байт-код и делает корректную оптимизацию.
Видят, что Миф о статье - Определяющий переменные цикла в цикле плох для производительности для подобного примера.
Можно демонтировать код с javap-c и проверить то, что на самом деле испускает компилятор. На моей установке (Java 1.5/mac скомпилированных с затмением), байт-код для цикла идентичен.
Первый код лучше, поскольку он ограничивает объем o
переменная к for
блок. С точки зрения производительности это не могло бы иметь никаких эффектов в Java, но это могло бы иметь в более низких компиляторах уровня. Они могли бы поместить переменную в регистр, если Вы делаете первое.
На самом деле, некоторые люди могли бы думать, что, если компилятор является немым, второй отрывок лучше с точки зрения производительности. Это - то, что некоторый преподаватель сказал мне в колледже, и я смеялся над ним для этого предложения! В основном компиляторы выделяют память на стеке для локальных переменных метода только однажды в начале метода (путем корректировки указателя вершины стека) и выпускают его в конце метода (снова путем корректировки указателя вершины стека, предположения, что это не C++, или это не имеет никаких деструкторов, которые назовут). Таким образом, все стековые локальные переменные в методе выделяются сразу, неважно, где они объявляются и какого количества памяти они требуют. На самом деле, если компилятор является немым, нет никакого различия в терминах производительности, но если это достаточно умно, первый код может на самом деле быть лучше, поскольку это поможет компилятору понять объем и время жизни переменной! Между прочим, если это действительно умно, там не должен нет абсолютно никакая разница в производительности, поскольку это выводит фактический объем.
Конструкция объекта с помощью new
полностью отличается от просто объявления его, конечно.
я думаю, что удобочитаемость более важна, что производительность и с точки зрения удобочитаемости, первый код определенно лучше.
Преждевременно не оптимизировать. Лучше, чем любой из них:
for(Object o : someList) {
o.doSomething();
}
, потому что это устраняет шаблон и разъясняет намерение.
, Если Вы не работаете над встроенными системами, в этом случае все ставки выключены. Иначе не пытайтесь перехитрить JVM.
Для заключения в кавычки Knuth, который может заключать Hoare в кавычки:
Преждевременная оптимизация является корнем всего зла.
, Произведет ли компилятор незначительно более быстрый код путем определения переменной вне цикла, спорно, и я предполагаю, что это не будет. Я был бы предположение , оно произведет идентичный байт-код.
Сравнивают это с количеством ошибок, Вы, вероятно, предотвратите правильно определяющим объем свою переменную с помощью объявления в цикле...