单例模式
确保一个类只有一个实例,而且自行实例化,并向整个系统提供这个实例
因此单例模式的构造函数是私有的,并且实例是static静态的,还需要提供一个静态方法getInstance()获取实例
单例模式分饿汉式和懒汉式
饿汉式
程序启动时就创建实例,一开始就创建实例并始终需要使用该实例
优点:线程安全,实现简单
缺点:无法延迟加载,会浪费资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Singleton { private: static Singleton instance; Singleton() = default; ~Singleton() = default; Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete;
public: static Singleton& getInstance() { return instance; } };
Singleton Singleton::instance;
|
懒汉式
首次调用静态方法获取实例时才创建实例
普通写法会出现线程不安全的情况,如果只加一种锁那么创建好实例之后仍然会每次加上锁再去判断,每次都会加锁影响性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <mutex>
class Singleton { private: static Singleton* instance; static std::mutex mutex_; Singleton() = default; ~Singleton() = default; Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete;
public: static Singleton* getInstance() { std::lock_guard<std::mutex> lock(mutex_); if (instance == nullptr) { instance = new Singleton(); } return instance; } };
Singleton* Singleton::instance = nullptr; std::mutex Singleton::mutex_;
|
判空 锁 判空 锁 这样的形式就会防止锁消耗性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <mutex>
class Singleton { private: static Singleton* instance; static std::mutex mutex_; Singleton() = default; ~Singleton() = default; Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete;
public: static Singleton* getInstance() { Singleton* tmp = instance; if (tmp == nullptr) { std::lock_guard<std::mutex> lock(mutex_); tmp = instance; if (tmp == nullptr) { tmp = new Singleton(); instance = tmp; } } return tmp; } };
Singleton* Singleton::instance = nullptr; std::mutex Singleton::mutex_;
|
C++实现单例模式的一些问题
C++的类内除了默认的构造函数,还有默认的拷贝构造和默认赋值运算符
所以我们需要将其禁用,使用=delete,防止出现外部的拷贝构造和赋值操作
另外懒汉式要想保证线程安全就必须使用指针去实现或C++11Meyers