Деструктор для статических полей.Реализация синглтона - PullRequest
13 голосов
/ 02 апреля 2012

Итак, классическая простая реализация Singleton выглядит следующим образом:

class Singleton
{
private:
    static Singleton* singleton;
    Singleton() {}
public:
    static Singleton* getInstance();        
};

СРР-файл

Singleton* Singleton::singleton = 0;

Singleton* Singleton::getInstance()
{
    if (!singleton)
    {
        singleton = new Singleton;
    }

    return singleton;
}

Я вижу здесь утечку памяти - потому что delete для new отсутствует. Но в C ++ нет статического деструктора, поэтому нам просто наплевать на утечку памяти?

Ответы [ 3 ]

26 голосов
/ 02 апреля 2012

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

В случае синглтона у нас нет утечки, потому что этот синглтон существует во всей программе,Его время жизни никогда не должно заканчиваться, и поэтому память, не возвращаемая, не является проблемой.

Тем не менее, приведенный выше код - это не то, как большинство людей реализует синглтон.Каноническая реализация C ++ будет выглядеть примерно так:

class Singleton
{
private:
    /* No instantiation. */
    Singleton() {}

    /* Explicitly disallow copying. */ 
    Singleton(const Singleton&) = delete;
    Singleton& operator= (const Singleton&) = delete;

    /* In C++03, the above would be written as
     *
     *    Singleton(const Singleton&);
     *    Singleton& operator= (const Singleton&);
     * 
     * and you'd just leave the methods unimplemented.
     */
public:
    static Singleton& getInstance();        
};

.cpp file:

Singleton& Singleton::getInstance() {
    /* Have a static local variable representing the unique instance.  Since
     * it's static, there is only one instance of this variable.  It's also only
     * initialized when getInstance is called.
     */
    static Singleton theInstance;
    return theInstance;
}

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

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

Надеюсь, это поможет!

3 голосов
/ 02 апреля 2012

Почему вы должны избегать такого кода, когда нет соответствия delete для new

Хотя нет фактической утечки памяти (в большинстве современных операционных систем), хужеДело в том, что ваш Singleton деструктор не вызывается.И если вы приобретете некоторые ресурсы, они, вероятно, будут утечки.

Что можно сделать здесь

Использовать умный указатель для хранения экземпляра, рассмотрим std::unique_ptr (с C ++11) или boost::auto_ptr

0 голосов
/ 02 апреля 2012

Когда переменная, локальная для функции, объявляется "статической", это означает, что она не размещена в стеке - и что ее значение сохраняется от одного вызова к следующему.

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