c++ - 为什么 C++ 单例实例化需要 do_nothing 方法?

标签 c++ design-patterns boost

我正在查看来自 http://www.boost.org/doc/libs/1_47_0/boost/pool/detail/singleton.hpp 的文档

我的问题:因为 create_object 是类 singleton_default 的静态成员,所以它的构造函数应该在 main 之前调用。从 object_creator 的构造函数中调用了 singleton_default::instance,这确保了 obj 在 main 之前被实例化。我不遵循的是需要 do_nothing 方法。文档提到它强制实例化 create_object 但不是类的静态成员应该在 main 启动之前初始化吗?因此,singleton_default::create_object 实例化应该不够好吗?

这是代码

// T must be: no-throw default constructible and no-throw destructible
template <typename T>
struct singleton_default
{
  private:
    struct object_creator
    {
      // This constructor does nothing more than ensure that instance()
      //  is called before main() begins, thus creating the static
      //  T object before multithreading race issues can come up.
      object_creator() { singleton_default<T>::instance(); }
      inline void do_nothing() const { }
    };
    static object_creator create_object;

    singleton_default();

  public:
    typedef T object_type;

    // If, at any point (in user code), singleton_default<T>::instance()
    //  is called, then the following function is instantiated.
    static object_type & instance()
    {
      // This is the object that we return a reference to.
      // It is guaranteed to be created before main() begins because of
      //  the next line.
      static object_type obj;

      // The following line does nothing else than force the instantiation
      //  of singleton_default<T>::create_object, whose constructor is
      //  called before main() begins.
      create_object.do_nothing();

      return obj;
    }
};
template <typename T>
typename singleton_default<T>::object_creator
singleton_default<T>::create_object;

我尝试删除 do_nothing 方法,但这在 main 之前停止了对象实例化。

最佳答案

您必须查看3.6.2 非局部变量初始化 部分中的标准。

首先是第2点的原则:

Variables with static storage duration (...) shall be zero-initialized before any other initialization takes place.

Constant initialization is performed: (...)

Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place. Dynamic initialization of a non-local variable with static storage duration is either ordered or unordered. Definitions of explicitly specialized class template static data members have ordered initialization.

然后在第 4 点中,对您的问题的解释(您的单例需要“动态初始化”):

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use of any function or variable defined in the same translation unit as the variable to be initialized.

这个do_nothing() 只是确保第一次使用和动态初始化的顺序。

如果没有 do_nothing(),全局静态 create_object() 就不需要在第一次调用 instance 之前初始化(),而这个函数内部的静态obj只会在第一次调用时被初始化,即在main()开始之后。

关于c++ - 为什么 C++ 单例实例化需要 do_nothing 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26701496/

相关文章:

适用于奇怪目标平台的 C++ 代码覆盖工具

swift - 将 Class.Type 传递给 Swift 函数

design-patterns - 接口(interface)的要点

c# - 聚合不同责任的最佳方式

c++ - SIMD C++ 库

c++ - QGraphicsView::drawBackground 中的故障网格

multithreading - 何时在 asio 中使用异步操作

c++ - C++ 中的签名保留装饰器模式?

c++ - 仅当底层类型具有这些构造函数时才实现模板类型构造函数

c++ - 序列化 boost 变体;非常奇怪和迟钝的编译器错误(MSVC 2010)