В C++ 11 это ориентировано на многопотоковое исполнение:
В§6.7 [stmt.dcl] p4, Если управление вводит объявление одновременно, в то время как переменная инициализируется, параллельное выполнение должно ожидать завершения инициализации.
В C++ 03:
Одна проблема состоит в том, что, если у Вас есть два одиночных элемента и они пытаются использовать друг друга во время конструкции и разрушения.
Read это: Открытие C++ статические проблемы порядка инициализации
вариация А на эту проблему состоит в том, если к одиночному элементу получают доступ от деструктора глобальной переменной. В этой ситуации был определенно уничтожен одиночный элемент, но получить метод все еще возвратит ссылку на уничтоженный объект.
существуют пути вокруг этого, но их грязны и не стоит делать. Просто не получайте доступ к одиночному элементу от деструктора глобальной переменной.
А Более безопасное определение, но ужасный:
я уверен, что можно добавить некоторые соответствующие макросы для уборки этого
SomeBaseClass &SomeClass::GetInstance()
{
#ifdef _WIN32
Start Critical Section Here
#elif defined(__GNUC__) && (__GNUC__ > 3)
// You are OK
#else
#error Add Critical Section for your platform
#endif
static SomeClass instance;
#ifdef _WIN32
END Critical Section Here
#endif
return instance;
}
Это не ориентировано на многопотоковое исполнение как показано. Язык C++ тих на потоках, таким образом, у Вас нет свойственных гарантий с языка. Необходимо будет использовать примитивы синхронизации платформы, например, Win32:: EnterCriticalSection (), для защиты доступа.
Ваш конкретный подход был бы проблематичным b/c, компилятор введет некоторый (неориентированный на многопотоковое исполнение) код для инициализации помех instance
на первом вызове, скорее всего, это будет, прежде чем тело функции начинает выполнение (и следовательно прежде чем любая синхронизация сможет быть вызвана.)
Используя глобальный/статичный членский указатель на SomeClass
и затем инициализирующий в синхронизируемом блоке оказался бы менее проблематичным для реализации.
#include <boost/shared_ptr.hpp>
namespace
{
//Could be implemented as private member of SomeClass instead..
boost::shared_ptr<SomeClass> g_instance;
}
SomeBaseClass &SomeClass::GetInstance()
{
//Synchronize me e.g. ::EnterCriticalSection()
if(g_instance == NULL)
g_instance = boost::shared_ptr<SomeClass>(new SomeClass());
//Unsynchronize me e.g. :::LeaveCriticalSection();
return *g_instance;
}
я не скомпилировал это так, это в иллюстративных целях только. Это также полагается на библиотеку повышения для получения того же времени жизни (или там о) как исходный пример. Можно также использовать станд.:: tr1 (C++ 0x).
Это совместно использует все общие сбои реализаций Singleton, а именно:
, я никогда рекомендую не использовать Singleton ни в каком производственном коде.
Согласно спецификациям, это также должно работать в VC ++. Кто-нибудь знает, есть ли это?
Просто добавьте ключевое слово volatile. Компилятор Visual C ++ должен затем сгенерировать мьютексы, если документ на msdn верен.
SomeBaseClass &SomeClass::GetInstance()
{
static volatile SomeClass instance;
return instance;
}