Порядок решения инициализации:
Во-первых, это всего лишь временный обходной путь, потому что у вас есть глобальные переменные, от которых вы пытаетесь избавиться, но просто еще не успели (вы в конечном итоге избавитесь от них? -)
class A
{
public:
// Get the global instance abc
static A& getInstance_abc() // return a reference
{
static A instance_abc;
return instance_abc;
}
};
Это гарантирует, что оно инициализируется при первом использовании и уничтожается при завершении работы приложения.
Многопоточная проблема:
C ++ 11 гарантирует гарантию того, что это потокобезопасно:
§6.7 [stmt.dcl] p4
Если элемент управления вводит объявление одновременно во время инициализации переменной, параллельное выполнение должно ожидать завершения инициализации.
Однако C ++ 03 официально не гарантирует того, что создание объектов статических функций является поточно-ориентированным. Технически, метод getInstance_XXX()
должен быть защищен критической секцией. С другой стороны, у gcc есть явный патч как часть компилятора, который гарантирует, что каждый объект статической функции будет инициализирован только один раз, даже при наличии потоков.
Обратите внимание: Не используйте дважды проверенный шаблон блокировки , чтобы попытаться избежать стоимости блокировки. Это не будет работать в C ++ 03.
Проблемы создания:
При создании проблем нет, потому что мы гарантируем, что он создан до того, как его можно будет использовать.
Проблемы с уничтожением:
Существует потенциальная проблема доступа к объекту после его уничтожения. Это происходит только в том случае, если вы обращаетесь к объекту из деструктора другой глобальной переменной (под глобальной я ссылаюсь на любую нелокальную статическую переменную).
Решение состоит в том, чтобы убедиться, что вы навязываете порядок уничтожения.
Помните, что порядок уничтожения является точным обратным порядку построения. Поэтому, если вы получаете доступ к объекту в своем деструкторе, вы должны гарантировать, что объект не был уничтожен. Чтобы сделать это, вы должны просто гарантировать, что объект полностью построен до того, как будет создан вызывающий объект.
class B
{
public:
static B& getInstance_Bglob;
{
static B instance_Bglob;
return instance_Bglob;;
}
~B()
{
A::getInstance_abc().doSomthing();
// The object abc is accessed from the destructor.
// Potential problem.
// You must guarantee that abc is destroyed after this object.
// To guarantee this you must make sure it is constructed first.
// To do this just access the object from the constructor.
}
B()
{
A::getInstance_abc();
// abc is now fully constructed.
// This means it was constructed before this object.
// This means it will be destroyed after this object.
// This means it is safe to use from the destructor.
}
};