首页 > 解决方案 > 初学者的 C++ 线程安全单例设计

问题描述

我希望创建一个静态 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;
};

加法: Meyer 的单例示例看起来像

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

              return inst;
       }

private:
       Singleton() {};
};

那么我的代码与 Meyer 的示例不一致吗?

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 相同的答案。

标签: c++thread-safetysingleton

解决方案


放弃 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,您将是安全的。不过,请谨慎使用。


推荐阅读