一.什么是单例模式
单例模式是一种设计模式,指在整个程序生命周期中有且仅有一个实例的类。可以分为懒汉式以及饿汉式。
懒汉式:只有在类的实例被使用时才生成唯一实例。但是存在线程安全以及内存泄露的问题。可以节省系统资源。
饿汉式:程序一旦开始运行就产生实例,自身没有线程安全问题。
二.特点
1.将构造函数设置为private,可以禁止栈上构造,避免生成多个实例。
2.将拷贝构造与拷贝赋值设置为delete。
3.使用static成员函数定义接口函数与实例指针保证唯一,使用互斥锁保证线程安全,使用智能指针避免内存泄漏。
三.实现
1.互斥锁+智能指针(懒汉式)
#include <iostream>
#include <mutex>
#include <memory>
class Single_instance{
using ptr = std::shared_ptr<Single_instance>;
public:
Single_instance(const Single_instance&) = delete;
Single_instance& operator=(const Single_instance&) = delete;
~Single_instance(){ std::cout << "Deconstruction call.\n"; }
static ptr get_instance(){
if(_instance == nullptr){
std::unique_lock<std::mutex> lock(_mux);
if(_instance == nullptr){
_instance = std::shared_ptr<Single_instance>(new Single_instance);
}
}
return _instance;
}
private:
Single_instance(){ std::cout << "Construction call.\n"; }
static ptr _instance;
static std::mutex _mux;
};
std::shared_ptr<Single_instance> Single_instance::_instance = nullptr;
std::mutex Single_instance::_mux;
int main(){
auto instance = Single_instance::get_instance();
auto instance1 = Single_instance::get_instance();
return 0;
}
运行构造函数调用一次,析构函数正常调用。
2.使用类静态变量返回实例引用(懒汉式推荐)
原理:当存在多线程申请实例时,局部静态变量只初始化一次是线程安全的。
#include <iostream>
class Single_instance {
public:
Single_instance(const Single_instance &) = delete;
Single_instance &operator=(const Single_instance &) = delete;
~Single_instance() { std::cout << "Deconstruction call.\n"; }
static Single_instance &get_instance() {
static Single_instance _instance;
return _instance;
}
private:
Single_instance() { std::cout << "Construction call.\n"; }
};
int main() {
Single_instance& instance = Single_instance::get_instance();
Single_instance& instance1 = Single_instance::get_instance();
return 0;
}
3.饿汉式单例
#include <iostream>
class Single_instance {
public:
Single_instance(const Single_instance &) = delete;
Single_instance &operator=(const Single_instance &) = delete;
static Single_instance *get_instance() {
return _instance;
}
static void delete_instance() {
if (_instance) {
delete _instance;
_instance = nullptr;
}
}
private:
Single_instance() { std::cout << "Construction call.\n"; }
~Single_instance() { std::cout << "Deconstruction call.\n"; }
static Single_instance *_instance;
};
Single_instance *Single_instance::_instance = new Single_instance;
int main() {
auto instance = Single_instance::get_instance();
auto instance1 = Single_instance::get_instance();
Single_instance::delete_instance();
return 0;
}