С ++ развращает мое мышление, как доверять авто сборщику мусора? - PullRequest
4 голосов
/ 06 июня 2010

Я использую для программирования в основном на C / C ++, что заставляет меня ежедневно работать с указателями и управлением памятью. В эти дни я пытаюсь разрабатывать, используя другие инструменты, такие как Java, Python и Ruby.

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

Так что мне нужно 2 мысли здесь, один из них - доверять сборщику мусора, скажем, с помощью тестов и доказательств того, что он действительно работает в Java, и знать, что я никогда не должен делать, чтобы получить мой код наилучшим образом быть.

И вторая мысль - это умение писать код на других языках. Я имею в виду, я знаю, что делать, я просто никогда не пишу код, как это обычно делают большинство программистов на Java или Python. Существуют ли книги для программистов на C ++, чтобы просто познакомить меня с правилами написания? (кстати, прости меня за мои ошибки в английском)

Ответы [ 5 ]

7 голосов
/ 06 июня 2010

Хорошая интуиция для использования памяти и общих утечек - это хорошо и в Java. То, что утечки памяти невозможны в Java, является распространенным заблуждением .

Тот, кто игнорирует тщательное управление памятью, например, быстро получит большие деревья висячих компонентов графического интерфейса, доступных из списков слушателей в долгоживущих моделях. (Был там, сделал это.)

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

Другое заблуждение заключается в том, что сборщик мусора "медленный". Алгоритмы довольно эффективны, и вам не следует беспокоиться об этом, пока вы не профилируете свою программу. Хорошим инструментом является JVisualVM (в комплекте с JDK). Этот инструмент покажет вам профилирование процессора и может помочь с возможными утечками памяти и отследить ненужные небольшие временные выделения.

5 голосов
/ 06 июня 2010

Следует иметь в виду одно отличие: в C ++ деструктор можно использовать для очистки любого вида ресурса, а не только памяти (т. Е. RAII ). В Java вы должны явно закрывать файлы, сокеты, соединения с хранилищами данных и т. Д. В блоке try - finally. Если вы поместите код очистки ресурса в метод завершения Java, он может быть вызван в неопределенное время в будущем или никогда, поэтому это не рекомендуется. Так что в некотором смысле это создает большую нагрузку для программиста, а не меньше.

Python находится где-то посередине - вы можете использовать оператор 'with' для автоматической очистки большинства ресурсов.

Две проблемы в управлении памятью в C ++ - утечка памяти и попытка использовать объект, который уже был уничтожен. Как уже отмечали другие, вы также можете получить утечки памяти в Java (и Python), если сохраните ссылку на объект, который вам больше не нужен, который, в свою очередь, может иметь ссылки на другие объекты. Утечки памяти в Java могут быть менее частыми, но когда они происходят, они могут быть намного больше, чем в C ++. Может помочь разумное использование слабых ссылок, а также присвоение нуля переменным, которые больше не нужны. Однако это приводит ко второй проблеме - если вы попытаетесь использовать переменную, вы получите исключение NullPointerException. Это более полезно, чем ошибка сегментации, которую вы, вероятно, получите в C ++, но все еще остается проблемой.

Итак, все, что вы узнали об управлении памятью в C ++, все еще применяется в Java, но вы должны сделать это и для других ресурсов.

2 голосов
/ 06 июня 2010

Мне кажется, я полностью понимаю вашу проблему мышления, в основном потому, что у меня есть точная противоположность ее:)

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

Чтобы привести конкретный пример, я бы предположил, что в C ++ есть определенные вещи, которые вы делаете в начале и в конце жизненного цикла объекта, что означает, что вы, скорее всего, должны обернуть их в свои собственные методы ( не конструкторы / деструкторы, имейте в виду! ) и сначала "обучайте" себя использовать их явно в C ++. Затем, когда вы переходите на Java, вы можете довольно легко перейти по аналогии с этим методом к другим привычкам программирования, и вместо того, чтобы царапать голову деструкторами и еще чем-то, просто реализуйте эти методы, оставив их пустыми. Таким образом, у вас есть не столь невидимый ментальный маркер для себя , который жизненный цикл объекта подходит к концу, и в конце концов, когда вы научитесь доверять этому, вы можете удалить его. Вам даже не нужно беспокоиться о накладных расходах, JVM будет оптимизировать эти избыточные вызовы методов в любом случае, пока тело метода пусто.

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

public class MentalHelpers {
    private MyFieldObject mfo;

    /**
     * Note the separate method for object creation.
     * This is actually good practice in general!
     */
    public MentalHelpers() {
        createObject();
    }

    private final void createObject() {
        mfo = new MyFieldObject();
    }

    private final void destroyObject() {
        // Do nothing! private or public, you decide.
    }

    public int incrementOne() {
        int i = 1;

        int ret = i++;

        freeInt(i);

        return ret;
    }

    private final freeInt(int i) {
        // Once again, do nothing!
    }
}

Вот и все, надеюсь, это полезно.

1 голос
/ 06 июня 2010

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

Снимок экрана GCViewer http://www.tagtraum.com/images/gcviewer-screenshot.png

0 голосов
/ 06 июня 2010

Я думаю, вы должны продолжать думать в стиле C ++. Создание объектов в Java обходится дороже, чем в C ++, поскольку у вас нет возможности разместить его в стеке. Не уверен, что это тот ответ, который вы искали.

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