Потокобезопасный однотонный дизайн C ++ для начинающих - PullRequest
0 голосов
/ 25 октября 2019

Я хочу создать статический объект Class, который должен оставаться в памяти во время работы программы. Объект должен быть инициализирован только один раз функцией init, и функция вывода всегда будет вызываться в статическом методе. Имеет ли смысл мой код и является ли он потокобезопасным?

class Singleton
{
public: 
       static void init(const int value)
       {
              static Singleton inst;
              inst.Value = value;
       }
       static int prnValue()
       {
               return Value;
       }

private:
       Singleton() {};
       static int Value;
};

int main()
{
       int inputValue = 10;

       Singleton::init(inputValue);
       cout << Singleton::prnValue();

       return 0;
}

Новое редактирование: Или я могу попробовать вот так?

class Singleton
{
public: 
       static Singleton& init(const int value)
       {
              static Singleton inst;
              inst.Value = value;

              return inst;
       }
       static int prnValue()
       {
               return Value;
       }

private:
       Singleton() {};
       static int Value;
};

Добавление: Пример синглтона Мейера выглядит как

class Singleton
{
public: 
       static Singleton& init()
       {
              static Singleton inst;

              return inst;
       }

private:
       Singleton() {};
};

Так не соответствует ли мой код примеру Мейера?

Try4: Как насчет этого?

class Singleton
{
public: 
       static Singleton& init(int value)
       {
              static Singleton inst(value);
              return inst;
       }
       static int prnValue()
       {
               return Value;
       }
private:
       Singleton(value) 
       {
              Value = value;
       }
       int Value;
};

Добавлен комментарий: Как передать аргумент в синглтоне , похоже, дает тот же ответ, что и Try4.

1 Ответ

0 голосов
/ 26 октября 2019

Откажитесь от Singleton и сделайте Value глобальную переменную const, инициализированную вспомогательной функцией.

Пример:

// anonymous namespace to bind the global to this file to prevent the static 
// initialization order fiasco
namespace 
{
    const int Value = ReadIniFile("section", "key", default_value);
}

Но что если вам нужно использовать эту переменную в другихфайлы? Лучший совет, который я получил, - нет. Но если вам необходимо, фиаско статического порядка инициализации должно быть преодолено. Вот быстрый способ сделать это аналогично тому, что вы видели до сих пор:

// Lazy loader function similar to Meyers Singleton
int Value()
{
    static int value = ReadIniFile("section", "key", default_value);
    return value;
}

Использование:

me_function_need_Value(Value());

Это гарантирует, что Value инициализируется прежде, чем кто-либо сможетстарайтесь использовать его независимо от того, какой файл нужен в вашем проекте. К сожалению, сейчас трудно понять, когда он выходит из области видимости, поэтому проблема на самом деле не исчезает. Он просто перемещен от начала программы к концу, где он немного более управляем. См. Порядок уничтожения статических объектов в C ++ . Убедитесь, что никто не использует Value после выхода main, и вы будете в безопасности. Тем не менее, используйте с осторожностью.

...