Если вы используете импорт подстановочных знаков, да, подстановочный импорт на самом деле является способом создания новых псевдонимов в вашем текущем пространстве имен для содержимого импортированного модуля. Если нет, вам нужно использовать пространство имен импортируемого модуля, как обычно.
Нет статики - вы не можете имитировать статику.
Также у Google есть инструмент, который будет измерять тестируемость вашего кода ...
См. Эту статью, в которой объясняется, почему блокировка с двойной проверкой не работает в C ++:
Каковы все общие неопределенные поведения, характерные для C ++ программист должен знать о?
Доктор Доббс: C ++ и опасности двойной проверки блокировки: Часть I
Моя реализация подобна 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;
Мы недавно пробежались через эту тему в моем классе 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 исчезает относительно других объектов? Но для простых приложений, это хорошо работает".
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.
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.
Другая альтернатива без выделения памяти: создайте синглтон, скажем, класса C
, если он вам нужен:
singleton<C>()
using
template <class X>
X& singleton()
{
static X x;
return x;
}
Ни этот, ни ответ Кэтэлина не являются автоматически потокобезопасными в текущем C ++, но будет на C ++ 0x.
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.
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.
Речь идет об управлении временем жизни объекта. Предположим, в вашем программном обеспечении больше, чем синглтонов. И они зависят от синглтона Logger. Предположим, что во время уничтожения приложения другой одноэлементный объект использует Logger для регистрации шагов уничтожения. Вы должны гарантировать, что Logger будет очищен в последнюю очередь. Поэтому, пожалуйста, также ознакомьтесь с этой статьей: http://www.cs.wustl.edu/~schmidt/PDF/ObjMan.pdf