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

    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实现。

    由于non-local static object是在main之前初始化的,默认进入main函数之前只有主线程运行,则有如下写法,犯了对template不熟悉的错误。

    #pragma once

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

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

    T Singleton_<T>::t_;

    这样定义编译不通过的!因为模板是编译期的多态,编译器用真实的类型替换T来生成相应的代码。

    上述类中的T在main之前构造,编译器无法推导出其真实的类型。

    下面看boost的singleton实现:

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


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

            inline void do_nothing()const
            {}
        };

        static object_creator create_object;

    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的初始化完全成功。

  • 相关阅读:
    .NET 4.5 is an in-place replacement for .NET 4.0
    python Argparse模块的使用
    linux的fork(), vfork()区别
    Linux 的 strace 命令
    NTFS系统的ADS交换数据流
    Git和.gitignore
    GIT常用命令
    OSChina码云试用
    tcpdump用法
    linux网卡混杂模式
  • 原文地址:https://www.cnblogs.com/kex1n/p/2006194.html
Copyright © 2011-2022 走看看