【问题标题】:getInstance - Class vs Method staticgetInstance - 类与方法静态
【发布时间】:2016-03-02 20:08:43
【问题描述】:

我知道关于何时初始化静态变量只有真正的基本保证。最重要的(对我而言)不能保证的是不同编译单元中变量的初始化顺序,这引发了以下问题。

我总是这样写我的单例类:

class A {
    ...
    public:
       static std::shared_ptr<A> getInstance();
    private:
       static std::shared_ptr<A> _instance;
}
== A.cpp ==
std::shared_ptr<A> A::getInstance() {
    if(!_instance)
       _instance = std::make_shared<A>();
    return _instance;
}

但是据我了解,如果我在任何其他静态对象的构造函数中调用此函数(在极少数情况下可能发生在 main开始执行)。

我的新想法如下:

 class A {
    ...
    public:
       static std::shared_ptr<A> getInstance();
}
== A.cpp ==
A& A::getInstance() {
    static std::shared_ptr<A> _instance = std::make_shared<A>();
    return _instance;
}

在我看来,这不仅更干净而且代码更好,因为现在我有一个保证的初始化顺序。

我的假设正确吗?

【问题讨论】:

  • 既然知道_instance在第一次调用getInstance的时候肯定会被初始化,那为什么还需要if语句呢?
  • 因为 _instance 没有值。默认初始化 std::shared_ptr 在其中存储一个空指针。
  • 如果是这样,为什么不立即用new A 初始化shared_ptr
  • 是的,你是对的,用新的 A 初始化它就可以了。我没有考虑到这一点。但还有一个更好的方法:使用 std::make_shared 进行初始化,它提供了更短的代码和 make_shared 的所有优点。我改变了我的例子。
  • 你是对的!我绝对不知道make_shared 比简单地使用new 构建更有效。谢谢!

标签: c++ static initialization singleton


【解决方案1】:

实际上_instance保证在第一次调用getInstance()之前就被初始化(前提是它们定义在同一个翻译单元中)

来自标准3.6.2-4 非局部变量的初始化

非局部变量的动态初始化是否带静态存储由实现定义 持续时间在 main 的第一条语句之前完成。如果初始化被推迟到某个时间点 在 main 的第一条语句之后,它应该出现在任何函数或变量的第一次 odr-use (3.2) 之前 在与要初始化的变量相同的翻译单元中定义。35

【讨论】:

    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 2011-03-17
    • 2016-09-25
    • 2011-11-10
    • 2012-04-19
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多