介绍

几个重点:

  • 构造函数为private
  • 提供一个获取单例对象指针的函数
  • 一个静态指针成员存储单例对象

注意:

  • 获取单例对象也可以获取对象引用,但要注意拷贝构造函数和赋值运算符
  • 如果有多线程访问单例,需要注意线程同步

范例

源码GitHub:CppDesignPattern

单线程

ifndef SIGLETON_H

define SIGLETON_H

/**

  • @brief 非线程安全单例,无多线程时使用
    /
    class Singleton {
    public:
    /*

  • @brief 单例模式,获取实例化对象
  • @param
  • @return 单例对象
    /
    static Singleton
    GetInstance();
    /**
  • @brief 单例模式,主动销毁实例化对象
  • @param
  • @return
    /
    static void DestoryInstance();
    private:
    /*

  • @brief 构造函数
    /
    Singleton();
    /*

  • @brief 单例模式在程序结束时自动删除单例的方法
    /
    class SingletonDel {
    public:
    ~SingletonDel() {
    if (m_instance != nullptr) {
    delete m_instance;
    m_instance = nullptr;
    }
    }
    };
    static SingletonDel m_singleton_del;///程序结束时销毁
    static Singleton
    m_instance; //单例对象指针
    };

    endif // SIGLETON_H

    //cpp

    include “sigleton.h”

    Singleton Singleton::m_instance = nullptr;
    Singleton
    Singleton::GetInstance() {
    if (m_instance == nullptr) {
    m_instance = new Singleton();
    }
    return m_instance;
    }

void Singleton::DestoryInstance() {
if (m_instance != nullptr) {
delete m_instance;
m_instance = nullptr;
}
}

Singleton::Singleton() {
}

多线程

ifndef THREAD_SAFE_SINGLETON_H

define THREAD_SAFE_SINGLETON_H

/**

  • @brief 线程安全单例,多线程时使用
    /
    class ThreadSafeSingleton {
    public:
    /*

  • @brief 单例模式,获取实例化对象
  • @param
  • @return 单例对象
    /
    static ThreadSafeSingleton
    GetInstance();
    /**
  • @brief 单例模式,主动销毁实例化对象
  • @param
  • @return
    /
    static void DestoryInstance();
    private:
    /*

  • @brief 构造函数
    /
    ThreadSafeSingleton();
    /*

  • @brief 单例模式在程序结束时自动删除单例的方法
    /
    class SingletonDel {
    public:
    ~SingletonDel() {
    if (m_instance != nullptr) {
    delete m_instance;
    m_instance = nullptr;
    }
    }
    };
    static ThreadSafeSingleton m_singleton_del;///程序结束时销毁
    static ThreadSafeSingleton
    m_instance; //单例对象指针
    };

    endif // THREAD_SAFE_SINGLETON_H

include “thread_safe_singleton.h”

include

include

namespace thread_safe_singleton_private {
static QMutex mutex;
}
ThreadSafeSingleton ThreadSafeSingleton::m_instance = nullptr;
ThreadSafeSingleton
ThreadSafeSingleton::GetInstance() {
if (m_instance == nullptr) {
QMutexLocker lock(&thread_safe_singleton_private::mutex);
if (m_instance == nullptr) {
m_instance = new ThreadSafeSingleton();
}
}
return m_instance;
}

void ThreadSafeSingleton::DestoryInstance() {
if (m_instance != nullptr) {
delete m_instance;
m_instance = nullptr;
}
}

ThreadSafeSingleton::ThreadSafeSingleton() {
}

上面的范例提供了主动销毁单例的方法同时提供了自动销毁的方法。 若主动销毁需注意其他存储了单例指针的对象

C++11单例模式实现

C++11保证静态成员构造的时候线程安全,所以可以避免在构造时通过线程锁的方式实现线程安全

ifndef CPP11_SIGLETON_H

define CPP11_SIGLETON_H

include

//C11的单例实现
//c11自动处理静态成员初始化竞争,是线程安全的
template
class Cpp11Sigleton {
public:
static T *GetInstance() {
static T instance;
return &instance;
}
};
class TestCpp11Sigleton {
friend class Cpp11Sigleton;
private:
TestCpp11Sigleton(){qDebug()<<”created”< };

endif // CPP11_SIGLETON_H

通过一个通用的单例模板类,并在需要单例类中将构造函数私有化,设置与模板类的friend关系即可实现多线程单例创建的安全。 注意返回的仍然是函数指针,若返回引用请注意拷贝和复制方法的处理

  • Class(const Class&); 拷贝
  • Class&operator=(const Class&); 复制

测试:

include

include

int main(int argc, char *argv[]) {
std::thread t1(Cpp11Sigleton::GetInstance);
t1.detach();
std::thread t2(Cpp11Sigleton::GetInstance);
t2.detach();
std::thread t3(Cpp11Sigleton::GetInstance);
t3.detach();
std::thread t4(Cpp11Sigleton::GetInstance);
t4.detach();
Cpp11Sigleton::GetInstance();
Cpp11Sigleton::GetInstance();
Cpp11Sigleton::GetInstance();
Cpp11Sigleton::GetInstance();
}

只会输出一次构造函数的qDebug()<<”created”<<this;

C++11单例模式实现构造时参数传入

11支持可变模板参数,所以可以用一个模板实现不同类型参数的构造,GetInstance方法改一下:

template
static T* GetInstance(Args&&… args) {
static T instance(std::forward(args)…);
return &m_pInstance;
}

相关链接:C++设计模式