创建型——单例模式C++实现
单例模式即保证一个类只有一个实例,并提供一个访问该单例的接口。
实例
1.懒汉式
用的时候才创建单例,“懒”。
Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_#include <iostream>
#include <string>
#include <mutex>class Singleton {public:static Singleton* GetInstance() {if (instance_ == nullptr) {// 加锁保证多个线程并发调用getInstance()时只会创建一个实例m_mutex_.lock();if (instance_ == nullptr) {instance_ = new Singleton();}m_mutex_.unlock();}return instance_;}private:Singleton() {}static Singleton* instance_;static std::mutex m_mutex_;
};#endif // SINGLETON_H_
这就是双重检验锁,保障了线程安全。第一个判空可加速判断是否已有单例,第二个锁内的判空是为了解决多线程问题(两个线程同时走到lock,且instance_都为nullptr)。
Singleton.cpp
#include "Singleton.h"// 静态变量instance初始化不要放在头文件中, 如果多个文件包含singleton.h会出现重复定义问题
Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::m_mutex_;
main.cpp
#include <iostream>
#include "Singleton.h"int main() {Singleton *s1 = Singleton::GetInstance();Singleton *s2 = Singleton::GetInstance();std::cout << "s1地址: " << s1 << std::endl;std::cout << "s2地址: " << s2 << std::endl;return 0;
}
编译运行:
$g++ -g main.cpp Singleton.cpp -std=c++11 -o singleton
$./singleton
s1地址: 0x95a040
s2地址: 0x95a040
2. 饿汉式
类初始化就创建单例,GetInstance()只是获取动作,“饿”。
Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_class Singleton {public:static Singleton* GetInstance() {return instance_;}private:Singleton() {}static Singleton* instance_;
};#endif // SINGLETON_H_
Singleton.cpp
#include "Singleton.h"Singleton* Singleton::instance_ = new Singleton();
main.cpp
#include <iostream>
#include "Singleton.h"int main() {Singleton *s1 = Singleton::GetInstance();Singleton *s2 = Singleton::GetInstance();std::cout << "s1地址: " << s1 << std::endl;std::cout << "s2地址: " << s2 << std::endl;return 0;
}
编译运行:
$g++ -g main.cpp Singleton.cpp -std=c++11 -o singleton
$./singleton
s1地址: 0x18a8040
s2地址: 0x18a8040
3. Meyers' Singleton
Meyers' Singleton是Scott Meyers提出的C++单例的推荐写法。它将单例对象作为局部static对象定义在函数内部:
#ifndef SINGLETON_H_
#define SINGLETON_H_class Singleton {public:static Singleton& GetInstance() {static Singleton instance;return instance;}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() {}
};#endif // SINGLETON_H_
需要C11支持(C11保证static成员初始化的线程安全)