{面试题2: 实现 Singleton 模式}

From 剑指Offer 何海涛 著

// 不好的解法一: 只适用于单线程环境
class Singleton1 {
    public:
        static Singleton1* getInstance(void) {
            if(instance == NULL) {
                instance = new Singleton1();
            }
            return instance;
        }
        
    private:
        static Singleton1 *instance;
        
    private:
        Singleton1(void) {
            
        }
        Singleton1(const Singleton1&);
        Singleton1& operator=(const Singleton1&);
        ~Singleton1(void) {
            
        }
        
        class NestedClass {
            public:
                ~NestedClass(void) {
                    delete Singleton1::instance;
                    Singleton1::instance =  NULL;
                }
        };
        static NestedClass justForSingleton; // 实现程序结束时, 释放 instance 占用的动态内存
};
// 不好的解法一(扩展): 只适用于单线程环境
class Singleton2 {
    public:
        static Singleton2& getInstance(void) {
            static Singleton2 instance; // 使用局部静态变量, 实现 instance 占用内存的释放
            return instance;
        }

    private:
        Singleton2(void) {

        }
        Singleton2(const Singleton2&);
        Singleton2& operator=(const Singleton2&);
        ~Singleton2(void) {

        }

};
// 可行的解法: 加同步锁前后两次判断实例是否存在
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
class Singleton1 {
    public:
        static Singleton1* getInstance(void) {
            if(instance == NULL) {
                pthread_mutex_lock(&mutex);
                if(instance == NULL) {
                    instance = new Singleton1();
                }
                pthread_mutex_unlock(&mutex);
            }
            return instance;
        }

    private:
        static Singleton1 *instance;


    private:
        Singleton1(void) {

        }
        Singleton1(const Singleton1&);
        Singleton1& operator=(const Singleton1&);
        ~Singleton1(void) {

        }

        class NestedClass {
            public:
                ~NestedClass(void) {
                    delete Singleton1::instance;
                    Singleton1::instance =  NULL;
                }
        };
        static NestedClass justForSingleton;
};

Singleton1* Singleton1::instance = NULL;
// 强烈推荐的解法: 利用静态成员变量
class Singleton3 {
    public:
        static Singleton3* getInstance(void) {
            return instance;
        }

    private:
        static Singleton3 *instance;


    private:
        Singleton3(void) {

        }
        Singleton3(const Singleton3&);
        Singleton3& operator=(const Singleton3&);
        ~Singleton3(void) {

        }

        class NestedClass {
            public:
                ~NestedClass(void) {
                    delete Singleton3::instance;
                    Singleton3::instance =  NULL;
                }
        };
        static NestedClass justForSingleton;
};

Singleton3* Singleton3::instance = new Singleton3(); // 在程序开始时就会产生一个该类的实例,并在以后仅返回此实例
// 强烈推荐的的解法: 实现按需创建实例, 但这里并没有实现(C++中实现按需创建, 似乎只能借助于锁机制)
class Singleton4 {
    public:
        static Singleton4* getInstance(void) {
            return &NestedClass::instance; // 实例在进入主程序前已完成初始化
        }

    private:
        Singleton4(void) {

        }
        Singleton4(const Singleton4&);
        Singleton4& operator=(const Singleton4&);
        ~Singleton4(void) {

        }

        class NestedClass {
            public:
                static Singleton4 instance;
        };
};
Singleton4 Singleton4::NestedClass::instance;

 

 

总结:

1. 程序在结束的时候,系统会自动析构所有的全局变量: 可以在类对象中添加一个静态类对象, 实现该类中静态变量占有的动态内存;

在单例类内部定义专有的嵌套类;
在单例类内定义私有的专门用于释放的静态成员;
利用程序在结束时析构全局变量的特性,选择最终的释放时机;
使用单例的代码不需要任何操作,不必关心对象的释放。

2. C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁, 实现线程安全性;

3. 静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。

参考:

http://blog.csdn.net/hackbuteer1/article/details/7460019

http://www.cnblogs.com/ccdev/archive/2012/12/19/2825355.html

posted @ 2015-04-19 11:23  long#long  阅读(405)  评论(0编辑  收藏  举报