一.什么是单例模式
单例模式是一种设计模式,指在整个程序生命周期中有且仅有一个实例的类。可以分为懒汉式以及饿汉式。
懒汉式:只有在类的实例被使用时才生成唯一实例。但是存在线程安全以及内存泄露的问题。可以节省系统资源。
饿汉式:程序一旦开始运行就产生实例,自身没有线程安全问题。
二.特点
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;
}