1 代码模板

class Singleton {
public:
    static Singleton * GetInstance(){
        static Singleton instance;
        return &instance;
    }
private:
    Singleton() {};
    Singleton(const Singleton);
    Singleton & operate = (const Singleton&);
};

2 要考虑的问题

内存泄露

最简单的单例写法是

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

但是这样一来, 由于是new出来的, 单例不会自动析构, 导致内存泄露. 于是可以考虑用:

static Singleton * GetInstance(){
    static Singleton instance;
    return &instance;
}

这是因为static成员变量会在程序退出时由系统负责调用析构函数.

多线程安全

c++11之后不用考虑这个问题, 编译器保证static变量只会被初始化一次.

但是早期的C++版本中, 如果两个线程在检查NULL的时候同时通过, 会导致出现多个instance的情况. 解决方法是双检锁:

static Singleton * GetInstance(){
    if(_instance == NULL){
        lock();
        if(_instance == NULL){
            _instance = Singleton();
        }
        unlock();
    }
    return _instance;
}

普通锁(即没有最外面的if)的话, 每次调用这个函数都会lock一下, 影响性能. 使用双检锁只在最开始_instance还是NULL的时候才会锁住. 后面就不会有影响了.

拷贝构造函数和=重载

光把构造函数私有化还不能完全保证单例, 还要把拷贝构造函数和=重载函数也私有化.

另外只声明不实现, 能使得友元类也无法直接调用构造函数(?)

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>