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

  • 相关阅读:
    DGA域名可以是色情网站域名
    使用cloudflare加速你的网站隐藏你的网站IP
    167. Two Sum II
    leetcode 563. Binary Tree Tilt
    python 多线程
    leetcode 404. Sum of Left Leaves
    leetcode 100. Same Tree
    leetcode 383. Ransom Note
    leetcode 122. Best Time to Buy and Sell Stock II
    天津Uber优步司机奖励政策(12月28日到12月29日)
  • 原文地址:https://www.cnblogs.com/kex1n/p/2006194.html
Copyright © 2011-2022 走看看