Принесите вам два разных варианта одноэлементного дизайна:
class SingletonCSM;
using SingletonCSMSp = std::shared_ptr < SingletonCSM > ;
class SingletonCSM
{
public:
~SingletonCSM() { spInstance = nullptr; }
static SingletonCSMSp GetInstance()
{
if (!spInstance)
spInstance = std::make_shared<SingletonCSM>();
return spInstance;
}
private:
SingletonCSM() {}
// will be intilized in the cpp: SingletonCSMSp SingletonCSM::spInstance = nullptr;
static SingletonCSMSp spInstance;
};
class SingletonFSV;
using SingletonFSVSp = std::shared_ptr < SingletonFSV > ;
class SingletonFSV
{
public:
~SingletonFSV() {}
static SingletonFSVSp GetInstance()
{
static SingletonFSVSp spInstance = std::make_shared<SingletonFSV>();
return spInstance;
}
private:
SingletonFSV() {}
};
Я всегда использую первый импл. SingletonCSM
, Я наткнулся, в нашем коде, на импл. лайк SingletonFSV
Учебный класс SingletonFSV
был реализован как часть проекта DLL. Это DLL, скомпилированная в VS 2013
, загружается в память исполняемым файлом и запускается.
Я обновил свой VS
в VS 2015
, скомпилировал проект DLL и запустил exe. Внезапно он разбился. Во время отладки я заметил, что сбой произошел в самой DLL. make_shared
называется в GetInstance()
возвращенный nullptr
и естественно вызвал ошибку сегментации.
Я изменился SingletonFSV
осущ. в SingletonCSM
и авария прекратилась. make_shared
вернул верный указатель и проблема была решена.
Я просто не понимаю, в чем была проблема и почему она была решена?
Когда вы кладете static
переменная внутри функции, она создается при первом вызове функции, поэтому она гарантированно была создана все вызывающие функции.
Члены, которые объявлены static
может быть создан до или после вызова вашей функции, потому что порядок инициализации между переводчиками не определено Таким образом, глобальный объект или static
объект может попытаться получить доступ к статическому члену до он был инициализирован системой времени выполнения.
Итак, на ваши вопросы:
- Можем ли мы рассмотреть как импл. как действительный импл. шаблона дизайна?
- Являются ли оба функционально одинаковыми?
Нет, используя static
член опасен, потому что вызывающий SingletonCSM::GetInstance()
может получить доступ к не созданному объекту, если nullptr
инициализация не произошла до вызова. static
Метод function является рекомендуемым методом, поскольку он гарантирует, что инициализация завершена для каждого вызывающего.
Я просто не понимаю, в чем была проблема и почему она была решена?
В вашем случае переход к более опасному способу, похоже, остановил ваш сбой. Я не могу объяснить, почему это так. Но вы, возможно, не устранили проблему, возможно, у вас есть неопределенное поведение в другом месте, которое просто перестало проявляться в этом случае, но позже может появиться с другим изменением.
Других решений пока нет …