Синглтон — вкл. использование статического члена класса против статической переменной члена

Принесите вам два разных варианта одноэлементного дизайна:

статический член класса

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

  1. Можем ли мы рассмотреть как импл. как действительный импл. шаблона дизайна?
  2. Являются ли оба функционально одинаковыми?

Фон

Учебный класс SingletonFSV был реализован как часть проекта DLL. Это DLL, скомпилированная в VS 2013, загружается в память исполняемым файлом и запускается.

проблема

Я обновил свой VS в VS 2015, скомпилировал проект DLL и запустил exe. Внезапно он разбился. Во время отладки я заметил, что сбой произошел в самой DLL. make_shared называется в GetInstance() возвращенный nullptr и естественно вызвал ошибку сегментации.

Решение

Я изменился SingletonFSV осущ. в SingletonCSM и авария прекратилась. make_shared вернул верный указатель и проблема была решена.

Вопрос

Я просто не понимаю, в чем была проблема и почему она была решена?

1

Решение

Когда вы кладете static переменная внутри функции, она создается при первом вызове функции, поэтому она гарантированно была создана все вызывающие функции.

Члены, которые объявлены static может быть создан до или после вызова вашей функции, потому что порядок инициализации между переводчиками не определено Таким образом, глобальный объект или static объект может попытаться получить доступ к статическому члену до он был инициализирован системой времени выполнения.

Итак, на ваши вопросы:

  1. Можем ли мы рассмотреть как импл. как действительный импл. шаблона дизайна?
  2. Являются ли оба функционально одинаковыми?

Нет, используя static член опасен, потому что вызывающий SingletonCSM::GetInstance() может получить доступ к не созданному объекту, если nullptr инициализация не произошла до вызова. static Метод function является рекомендуемым методом, поскольку он гарантирует, что инициализация завершена для каждого вызывающего.

Я просто не понимаю, в чем была проблема и почему она была решена?

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]