C ++ Singleton дизайн шаблона

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

661
задан FruitBreak 31 October 2012 в 10:58
поделиться

9 ответов

Нет статики - вы не можете имитировать статику.

Также у Google есть инструмент, который будет измерять тестируемость вашего кода ...


Экземпляр синглтона, объявленный как статическая переменная метода GetInstance, является ли он потокобезопасным?

См. Эту статью, в которой объясняется, почему блокировка с двойной проверкой не работает в C ++:
Каковы все общие неопределенные поведения, характерные для C ++ программист должен знать о?
Доктор Доббс: C ++ и опасности двойной проверки блокировки: Часть I

1032
ответ дан 22 November 2019 в 21:37
поделиться

Моя реализация подобна Galik. Различием является моя реализация, позволяет общим указателям очищать выделенную память, в противоположность содержанию на память, пока из приложения не выходят, и статические указатели очищены.

#pragma once

#include <memory>

template<typename T>
class Singleton
{
private:
  static std::weak_ptr<T> _singleton;
public:
  static std::shared_ptr<T> singleton()
  {
    std::shared_ptr<T> singleton = _singleton.lock();
    if (!singleton) 
    {
      singleton.reset(new T());
      _singleton = singleton;
    }

    return singleton;
  }
};

template<typename T>
std::weak_ptr<T> Singleton<T>::_singleton;
0
ответ дан 22 November 2019 в 21:37
поделиться

Мы недавно пробежались через эту тему в моем классе EECS. Если Вы хотите посмотреть на примечания лекции подробно, посетить http://umich.edu/~eecs381/lecture/IdiomsDesPattsCreational.pdf

существует два способа, которыми я знаю для создания Singleton-класса правильно.

Первый Путь:

Реализация это подобный пути у Вас есть он в Вашем примере. Что касается разрушения, "Одиночные элементы обычно выносят в течение продолжительности прогона программы; большая часть OSs восстановит память и большинство других ресурсов, когда программа завершится, таким образом, существует аргумент в пользу того, чтобы не вызвать беспокойство об этом".

Однако это - хорошая практика для чистки при завершении программы. Поэтому можно сделать это со вспомогательным статическим классом SingletonDestructor и объявить что как друг в Singleton.

class Singleton {
public:
  static Singleton* get_instance();

  // disable copy/move -- this is a Singleton
  Singleton(const Singleton&) = delete;
  Singleton(Singleton&&) = delete;
  Singleton& operator=(const Singleton&) = delete;
  Singleton& operator=(Singleton&&) = delete;

  friend class Singleton_destroyer;

private:
  Singleton();  // no one else can create one
  ~Singleton(); // prevent accidental deletion

  static Singleton* ptr;
};

// auxiliary static object for destroying the memory of Singleton
class Singleton_destroyer {
public:
  ~Singleton_destroyer { delete Singleton::ptr; }
};

Singleton_destroyer будет создан на запуске программы, и, "когда программа завершится, все глобальные / статические объекты уничтожаются кодом завершения работы библиотеки времени выполнения (вставленный компоновщиком), таким образом, the_destroyer будет уничтожен; его деструктор удалит Singleton, выполняя его деструктор".

1117-секундный Путь

Это называют Singleton Meyers, созданной мастером C++ Scott Meyers. Просто определите get_instance () по-другому. Теперь можно также избавиться от членской переменной указателя.

// public member function
static Singleton& Singleton::get_instance()
{
  static Singleton s;
  return s;
}

Это аккуратно, потому что возвращенное значение ссылкой, и можно использовать . синтаксис вместо -> для доступа к членским переменным.

"Компилятор автоматически создает код, который создает' первый раз через объявление, не после этого, и затем удаляет статический объект при завершении программы".

Примечание также, что с Singleton Meyers "можно войти в очень трудную ситуацию, если объекты полагаются друг на друга во время завершения - когда Singleton исчезает относительно других объектов? Но для простых приложений, это хорошо работает".

0
ответ дан 22 November 2019 в 21:37
поделиться

It is indeed probably allocated from the heap, but without the sources there is no way of knowing.

The typical implementation (taken from some code I have in emacs already) would be:

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

...and rely on the program going out of scope to clean up afterwards.

If you work on a platform where cleanup must be done manually, I'd probably add a manual cleanup routine.

Another issue with doing it this way is that it isn't thread-safe. In a multithreaded environment, two threads could get through the "if" before either has a chance to allocate the new instance (so both would). This still isn't too big of a deal if you are relying on program termination to clean up anyway.

2
ответ дан 22 November 2019 в 21:37
поделиться

The solution in the accepted answer has a significant drawback - the destructor for the singleton is called after the control leaves the main() function. There may be problems really, when some dependent objects are allocated inside main.

I met this problem, when trying to introduce a Singleton in the Qt application. I decided, that all my setup dialogs must be Singletons, and adopted the pattern above. Unfortunately, Qt's main class QApplication was allocated on stack in the main function, and Qt forbids creating/destroying dialogs when no application object is available.

That is why I prefer heap-allocated singletons. I provide an explicit init() and term() methods for all the singletons and call them inside main. Thus I have a full control over the order of singletons creation/destruction, and also I guarantee that singletons will be created, no matter whether someone called getInstance() or not.

6
ответ дан 22 November 2019 в 21:37
поделиться

Другая альтернатива без выделения памяти: создайте синглтон, скажем, класса C , если он вам нужен:

singleton<C>()

using

template <class X>
X& singleton()
{
    static X x;
    return x;
}

Ни этот, ни ответ Кэтэлина не являются автоматически потокобезопасными в текущем C ++, но будет на C ++ 0x.

9
ответ дан 22 November 2019 в 21:37
поделиться

You could avoid memory allocation. There are many variants, all having problems in case of multithreading environment.

I prefer this kind of implementation (actually, it is not correctly said I prefer, because I avoid singletons as much as possible):

class Singleton
{
private:
   Singleton();

public:
   static Singleton& instance()
   {
      static Singleton INSTANCE;
      return INSTANCE;
   }
};

It has no dynamic memory allocation.

36
ответ дан 22 November 2019 в 21:37
поделиться

Being a Singleton, you usually do not want it to be destructed.

It will get torn down and deallocated when the program terminates, which is the normal, desired behavior for a singleton. If you want to be able to explicitly clean it, it's fairly easy to add a static method to the class that allows you to restore it to a clean state, and have it reallocate next time it's used, but that's outside of the scope of a "classic" singleton.

46
ответ дан 22 November 2019 в 21:37
поделиться

Речь идет об управлении временем жизни объекта. Предположим, в вашем программном обеспечении больше, чем синглтонов. И они зависят от синглтона Logger. Предположим, что во время уничтожения приложения другой одноэлементный объект использует Logger для регистрации шагов уничтожения. Вы должны гарантировать, что Logger будет очищен в последнюю очередь. Поэтому, пожалуйста, также ознакомьтесь с этой статьей: http://www.cs.wustl.edu/~schmidt/PDF/ObjMan.pdf

0
ответ дан 22 November 2019 в 21:37
поделиться
Другие вопросы по тегам:

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