Menu Home

C++: 单例模式和缺陷

实现一个单例模式

class Singleton {
    private:
        Singleton() { cout << "Singleton::constructor" << endl; }
        ~Singlton() { cout << "Singleton::destructor" << endl; }
        Singleton(const Singleton&) {};
        Singleton &operator=(const Singleton&) {};
    public:
        static Singleton* getInstance() {
            if(m_aInstance == NULL) {
                m_aInstance = new Singleton();
            }
            return m_aInstance;
        }
        void show() {
            cout << "Singleton::show" << endl;
        }
    private:
        static Singleton* m_aInstance;
};

Singleton* Singleton::m_aInstance = NULL;

int main(int argc, char **argv) {
    Singleton* aSingleton = Singleton::getInstance();
    aSingleton->show(); 
    return 0;
}
编译执行上面的代码,输出如下:

Singleton::constructor
Singleton::show
我们发现上面的输出并没有调用到Singleton的虚构函数,Singleton的资源可能没有被释放。现在的问题是要怎么才能在程序退出的时候正确释放Singleton的资源。我们注意到这样一个事实:

系统会自动调用在栈和静态数据区上分配的对象的析构函数来释放资源。

修改程序如下:

class Singleton {
    private:
        Singleton() { cout << "Singleton::constructor" << endl; }
        ~Singleton() { cout << "Singleton::destructor" << endl; }
        Singleton(const Singleton&) {};
        Singleton &operator=(const Singleton&) {};
    public:
        static Singleton* getInstance() {
            if(m_aInstance == NULL) {
                m_aInstance = new Singleton();
            }
            return m_aInstance;
        }
        void show() {
            cout << "Singleton::show" << endl;
        }

    private:
        class Garbage{
            public:
                ~Garbage() {
                    if(m_aInstance != NULL) {
                        delete m_aInstance;
                    }
                }
        };
    
    private:
        static Singleton* m_aInstance;
        static Garbage m_garbage;
};

Singleton* Singleton::m_aInstance = NULL;
Singleton::Garbage Singleton::m_garbage;

int main(int argc, char **argv) {
    Singleton* aSingleton = Singleton::getInstance();
    aSingleton->show(); 
    return 0;
}
编译上面的代码并执行,输出如下:

Singleton::constructor
Singleton::show
Singleton::destructor

我们看到Singleton::destructor被明确的执行了。

相关阅读: 递归模板实现单例模式