zoukankan      html  css  js  c++  java
  • static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符

    一、static 与单例模式

    单例模式也就是简单的一种设计模式,它需要:

    保证一个类只有一个实例,并提供一个全局访问点

    禁止拷贝

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    #include <iostream>
    using namespace std;

    class Singleton
    {
    public:
        static Singleton *GetInstance()
        {
            if (instance_ == NULL)
            {
                instance_ = new Singleton;
            }
            return instance_;
        }

        ~Singleton()
        {
            cout << "~Singleton ..." << endl;
        }
    private:
        Singleton(const Singleton &other);
        Singleton &operator=(const Singleton &other);
        Singleton()
        {
            cout << "Singleton ..." << endl;
        }
        static Singleton *instance_;
    };

    Singleton *Singleton::instance_;

    int main(void)
    {
        //Singleton s1;
        //Singleton s2;

        Singleton *s1 = Singleton::GetInstance();
        Singleton *s2 = Singleton::GetInstance();

        //Singleton s3(*s1);        // 调用拷贝构造函数

        return 0;
    }

    上述程序虽然调用了两个GetInstance函数,但只调用一次构造函数,即创建一个对象。将赋值运算符和拷贝构造函数声明为私有,禁止拷贝。但程序存在一个问题就是对象生存期到时不会被析构。

    为了解决对象不会被析构的问题,可以使用一个静态的嵌套类对象来解决:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    #include <iostream>
    using namespace std;

    class Singleton
    {
    public:
        static Singleton *GetInstance()
        {
            if (instance_ == NULL)
            {
                instance_ = new Singleton;
            }
            return instance_;
        }

        ~Singleton()
        {
            cout << "~Singleton ..." << endl;
        }

        //static void Free()
        //{
        //  if (instance_ != NULL)
        //  {
        //      delete instance_;
        //  }
        //}

        class Garbo
        {
        public:
            ~Garbo()
            {
                if (Singleton::instance_ != NULL)
                {
                    delete instance_;
                }
            }
        };
    private:
        Singleton(const Singleton &other);
        Singleton &operator=(const Singleton &other);
        Singleton()
        {
            cout << "Singleton ..." << endl;
        }
        static Singleton *instance_;

        static Garbo garbo_;    // 利用对象的确定性析构
    };

    Singleton::Garbo Singleton::garbo_;
    Singleton *Singleton::instance_;

    int main(void)
    {
        //Singleton s1;
        //Singleton s2;

        Singleton *s1 = Singleton::GetInstance();
        Singleton *s2 = Singleton::GetInstance();

        //Singleton s3(*s1);        // 调用拷贝构造函数


        return 0;
    }

    利用静态嵌套对象的确定性析构会调用Garbo类的析构函数,在析构函数内delete 单例类的指针。

    上面办法比较繁琐,也可以返回局部静态对象的引用来解决:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    #include <iostream>
    using namespace std;

    class Singleton
    {
    public:
        static Singleton &GetInstance()
        {
            static Singleton instance;      // 局部静态对象
            return instance;
        }

        ~Singleton()
        {
            cout << "~Singleton ..." << endl;
        }

    private:
        Singleton(const Singleton &other);
        Singleton &operator=(const Singleton &other);
        Singleton()
        {
            cout << "Singleton ..." << endl;
        }
    };

    int main(void)
    {
        Singleton &s1 = Singleton::GetInstance();
        Singleton &s2 = Singleton::GetInstance();



        return 0;
    }

    局部静态对象只会初始化一次,所以调用多次GetInstance函数得到的是同一个对象。由于函数内使用了静态对象,故不是线程安全的。实际上也可以使用auto_ptr 智能指针 来解决,程序如下,更详细的对auto_ptr 的讨论参见这里

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #include <iostream>
    #include<memory>
    using namespace std;

    class Singleton
    {
    public:
        static Singleton *GetInstance()
        {
            if (instance_.get() == NULL)
            {
                instance_ = auto_ptr<Singleton>(new Singleton);
            }
            return instance_.get();
        }

        ~Singleton()
        {
            cout << "~Singleton ..." << endl;
        }
    private:
        Singleton(const Singleton &other);
        Singleton &operator=(const Singleton &other);
        Singleton()
        {
            cout << "Singleton ..." << endl;
        }
        static auto_ptr<Singleton> instance_;
    };

    auto_ptr<Singleton> Singleton::instance_;

    int main(void)
    {
        //Singleton s1;
        //Singleton s2;

        Singleton *s1 = Singleton::GetInstance();
        Singleton *s2 = Singleton::GetInstance();

        //Singleton s3(*s1);        // 调用拷贝构造函数

        return 0;
    }

    实际上,上述所有的单例模式例子都不是线程安全的,设想如果两个线程同时运行到语句if (instance == null),而此时该实例的确没有创建,那么两个线程都会创建一个实例。如果不希望加锁实现线程安全,可以使用饿汉模式(即在main函数之前先生成一个实例):


    或者通过加锁方式实现,请参考这里


    二、const成员函数、const 对象、mutable修饰符

    (一)、const 成员函数

    const成员函数不会修改对象的状态

    const成员函数只能访问数据成员的值,而不能修改它

    (二)、const 对象

    如果把一个对象指定为const,就是告诉编译器不要修改它
    const对象的定义:

    const 类名 对象名(参数表);

    const对象不能调用非const成员函数

    用mutable修饰的数据成员即使在const对象或在const成员函数中都可以被修改。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    #include <iostream>
    using namespace std;

    class Test
    {
    public:
        Test(int x) : x_(x), outputTimes_(0)
        {

        }
        int GetX() const
        {
            cout << "const GetX ..." << endl;
            //x_ = 100;
            return x_;
        }

        int GetX()
        {
            cout << "GetX ..." << endl;
            return x_;
        }

        void Output() const
        {
            cout << "x=" << x_ << endl;
            outputTimes_++;
        }

        int GetOutputTimes() const
        {
            return outputTimes_;
        }
    private:
        int x_;

        mutable int outputTimes_;
    };

    int main(void)
    {
        const Test t(10);
        t.GetX();

        Test t2(20);
        t2.GetX();

        t.Output();
        t.Output();
        cout << t.GetOutputTimes() << endl;
        return 0;
    }



    三、const 用法总结

    可以对const 的用法做个小总结:



    参考:

    C++ primer 第四版
    Effective C++ 3rd
    C++编程规范

  • 相关阅读:
    11.组件-组件中的data和methods
    09.组件-创建组件的方式2
    10.组件-创建组件的方式3
    07.动画-列表动画
    08.组件-创建组件的方式1
    关于苹果iBeacon官方文档解析
    IOS-代码书写规范
    IOS- 1970ms时间计算
    关于tableview顶部留白问题
    IOS-网络请求数据解析道数组程序崩溃问题
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471038.html
Copyright © 2011-2022 走看看