【问题标题】:beginner's C++ thread-safe singleton design初学者的 C++ 线程安全单例设计
【发布时间】:2020-02-22 04:14:22
【问题描述】:

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

添加评论: How to pass argument in a singleton 似乎提供了与 Try4 相同的答案。

【问题讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 在多线程上下文中(从您的问题文本中不确定),您可以使用经典的 std::call_once 库函数来保护初始化。线索就在名字里。

标签: c++ thread-safety singleton


【解决方案1】:

放弃 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);
}

但是如果你需要在其他文件中使用这个变量呢?我得到的最好的建议是不要。但如果必须,static initialization order fiasco 需要被克服。这是一种与您目前看到的类似的快速方法:

// 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 在任何人都可以尝试使用它之前被初始化,无论您的项目中的哪个文件需要它。不幸的是,现在很难弄清楚它何时超出范围,因此问题并没有真正消失。它只是从程序的开头移到了更易于管理的结尾。见Destruction order of static objects in C++。 确保在main 退出后没有人使用Value,这样你就安全了。不过,请谨慎使用。

【讨论】:

    猜你喜欢
    • 2018-09-08
    • 1970-01-01
    • 2014-06-13
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2012-09-04
    相关资源
    最近更新 更多