2015-11-12 3 views
1

У меня есть класс Properties, который загружает некоторые свойства из файла. Я хочу иметь только один экземпляр свойств и быть доступным из всех классов. Вот что я сделал в очень Java духе:C++ static member deconstructor, вызываемый несколько раз

class Properties{ 
public: 
    static Properties getInstance(); 
    ~Properties(); 
private: 
    Properties(); 
    static Properties instance; 
} 

Так класс имеет статический член сам по себе, который может мне получить доступ из функции GetInstance(). Затем я получаю различные функции для получения свойств объекта. Например.

Properties::getInstance().getUseDepthInpainting(); 

Странно, что только в первый раз, когда я пытаюсь получить доступ к собственности, я получаю правильное значение. Кроме этого, я получаю нулевые значения. Затем я перешел к положению печати в конструкторе, а другой - в деконструкторе. Хотя, как и ожидалось, конструктор вызывается только в первый раз, когда я вызываю getInstance(), деконструктор вызывается каждый раз, когда вызывается getInstance(). Может кто-то объяснить, почему это происходит, и каков правильный способ делать это?

+2

Хотя ваша непосредственная проблема - это, вероятно, копии, которые вы создаете, я хотел бы указать, что это, вероятно, злоупотребление синглтонным шаблоном для чего-то, что не должно быть синглом. Синглтон следует использовать только тогда, когда существует технический предел количества экземпляров, например, при абстрагировании конечного физического ресурса. – Alex

ответ

3

Singleton работает на 3-х ингредиентах:

  • частные ссылочного
  • частного конструктор
  • общественного Творения функции ("экземпляр", "деЫпзЬапс" и т.д.)

Хитрость идет как это:

  1. call the cre АЦИОНАЛЬНЫЙ функция
  2. на созидательные функции проверки, если указатель является нулевым
  3. если указатель является нулевым - создать новый экземпляр на нем
  4. вернуть указатель

в вашем фрагменте кода isntance не удерживается указатель, но является полностью стоящим объектом. если изменить экземпляр быть от типа Properties* и getInstance() вернуть Properties* (или Properties&) Я думаю, что проблема будет решена

В настоящее время на грани 2016 года, правильный способ написать singletone выглядит следующим образом:

class Singleton{ 

private: 
    static std::unique_ptr<Singleton> instance; 
    static std::once_flag onceFlag; 
    Singleton(); 

public: 
    static Singleton& getInstance(){ 
    std::call_once(onceFlag,[&]{ 
     instance = std::unique_ptr<Singleton>(new Singleton());  
    }); 
    return *instance; 
    } 

}; 
+1

Почему так сложно 'getInstance'? Какое преимущество по сравнению с просто возвращением ссылки на статический объект? – user2079303

+1

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

+1

@DavidHaim Это устарело. C++ 11 имеет магическую статику, которая делает это для вас, и с тех пор, как вы растянулись на «рубеж 2016 года», можно предположить, что 2011 год прошел. – nwp

2

Ваш метод getInstance возвращает свойства по значению, что означает вернуть копию фактического экземпляра. Эта копия уничтожается каждый раз, когда она выходит из сферы действия.

Раствор возвращает ссылку на instance объекта, путем изменения подписи вашей функции:

static Properties& getInstance(); 

Это, вероятно, даже лучше, если ваш объект только для чтения, чтобы сделать его const ссылка так что ваш абонент не может идти возится в свойствах объекта:

static const Properties& getInstance(); 
2

статический Разрушитель член называется несколько раз

Нет, деструктор статического элемента вызывается только один раз.

Хотя, как и ожидалось, конструктор вызывается только первый раз, когда я называю GetInstance(), то Разрушитель вызывается каждый раз, раз, когда деЫпзЬапсе() называется .. Может кто-нибудь объяснить, почему это происходит, и что это правильный способ сделать это?

Деструктор вызывается для каждой копии instance, возвращаемых getInstance, когда они разрушаются. Конструктор по умолчанию вызывается только один раз: другие экземпляры создаются с использованием конструктора-копии.

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

1

Хотя, как и ожидалось, конструктор вызывается только первый раз, когда я вызов деЫпзЬапсе(), то Разрушитель вызывается каждый раз, раз, когда деЫпзЬапсе() называется.

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

Удалить копии и переместить конструкторы и операторы присваивания.

Это правильный синглтон:

class Singleton 
{ 
public: 
    static Singleton & Instance() 
    { 
     // Since it's a static variable, if the class has already been created, 
     // It won't be created again. 
     // And it **is** thread-safe in C++11. 

     static Singleton myInstance; 

     // Return a reference to our instance. 
     return myInstance; 
    } 

    // delete copy and move constructors and assign operators 
    Singleton(Singleton const&) = delete;    // Copy construct 
    Singleton(Singleton&&) = delete;     // Move construct 
    Singleton& operator=(Singleton const&) = delete; // Copy assign 
    Singleton& operator=(Singleton &&) = delete;  // Move assign 

    // Any other public methods 

protected: 
    Singleton() 
    { 
     // Constructor code goes here. 
    } 

    ~Singleton() 
    { 
     // Destructor code goes here. 
    } 

    // And any other protected methods. 
} 

От rosettacode.

Смежные вопросы