zoukankan      html  css  js  c++  java
  • [转] boost库的Singleton的实现以及static成员的初始化问题

    http://www.cnblogs.com/kex1n/archive/2011/04/05/2006194.html

    effectie c++的条款4中提到:

    (global对象,定义在namespace内的对象,class内的static对象,函数内的static对象,file作用域内的 static对象)统称为static对象。其中函数内的static对象又叫local static object, 其他的叫non-local static object。

    non-local static object的初始化顺序是没有定义的,local static object在函数第一次调用时构造初始化。

    还有:non-local static object会在main函数之前被初始化。

    #pragma once
    #include <iostream>
    using namespace std;

    class Foo
    {
    public:
        Foo()
        {
            cout<<"Foo create!"<<endl;
        }
    };

    class Test
    {
    public:
        Test() {}
        Foo GetX() const{ return x_;}
    private:
        static Foo x_;
    };

    Foo Test::x_;

    即使在main函数中未初始化Test对象,仍会看到Foo Create的提示,所以non-local static object在main函数之前初始化的。

    普通的singleton模式:

    #pragma once
    template<typename T>
    class Singleton_
    {
    public:
        static T&Instance()
        {

       static T t_;
            return t_;
        }
    private:
        Singleton_() {}
    };

    多线程的时候此方法不给力,可以用加锁的办法,参见ACE实现的双重加锁优化的singleton实现。或要求使用者在main的早期或多线程环境之前把所有单件各调用一次instance()

    由于non-local static object是在main之前初始化的,默认进入main函数之前只有主线程运行,则有如下写法

    #pragma once

    template<typename T>
    class Singleton_
    {
    public:
        static T&Instance()
        {
            return t_;
        }

    private:
        Singleton_() {}

        static T t_;
    };

    template <typename T> T Singleton_<T>::t_;

    这样实现的问题是,无法预知对象的生成的顺序,如果多个单件对象有初始化次序要求会出现问题,比如一个单件构造函数中会调用另一个单件的instance(),而那个单件还没有构造。
    Boost的实现可以解决这两个问题。

    下面看boost的singleton实现:

    class Widget
    {
    public:
        Widget()
        {
            cout<<"Widget Creat"<<endl;
        }
    };


    template <typename T>
    struct Singleton
    {

    private:
        struct object_creator
        {
            object_creator()
            {
                Singleton<T>::instance();
            }

            inline void do_nothing()const
            {}
        };

        static object_creator create_object;

        Singleton () {}

    public:
        typedef T object_type;
        static object_type& instance()
        {
            static object_type obj;
            create_object.do_nothing();
            return obj;
        }
    };


    //声明一个全局变量template <typename T> Singleton<T>::create_object
    typename Singleton<T>::object_creator       Singleton<T>::create_object;

    int main()
    {
        Widget& w = Singleton<Widget>::instance();

        return 0;
    }

    没有使用锁机制,而是充分利用了C++的语言特性较好的解决了多线程情况下使用singleton的问题。
    boost的singleton的实现基于以下假设:良好的设计在进入main函数之前应该是单线程的。
    我们可以使用全局变量的方式来设计singleton,并且保证在使用该singleton之前其已经被正确的初始化。

    在进入main之前,唯一的主线程开始构造Singleton<T>::create_object,在其构造函数之内调用 Singleton的instance函数,并在该函数内生成Singleton对象,至于函数donoting(),去掉之后照样可以通过编译,我想原 因可能是为了再次保证singleton的初始化完全成功。

  • 相关阅读:
    翻译:《实用的Python编程》03_04_Modules
    翻译:《实用的Python编程》03_03_Error_checking
    翻译:《实用的Python编程》03_02_More_functions
    翻译:《实用的Python编程》03_01_Script
    翻译:《实用的Python编程》03_00_Overview
    翻译:《实用的 Python 编程》02_07_Objects
    翻译:《实用的Python编程》02_06_List_comprehension
    生成器
    python编码
    python迭代器
  • 原文地址:https://www.cnblogs.com/qiangxia/p/4323876.html
Copyright © 2011-2022 走看看