单例模式
考察内容:
- 懒汉
- 线程安全
- 资源释放
为何静态成员函数可调用ctor? 静态成员函数和成员函数的区别在于是否有this参数,但由于ctor不存在this参数,故静态成员函数可调用
//基础版本
class Singleton{
protected:
Singleton() = default;
~Singleton() = default;
public:
static Singleton* get_instance(){
if(_instance==nullptr)
_instance=new Singleton();
return _instance;
}
Singleton(const Singleton& rhs)=delete;
Singleton& operator=(const Singleton&) = delete;
private:
static Singleton* _instance;
}
//定义
Singleton* Singleton::_instance=nullptr;
//线程安全资源安全版本
class Singleton {
using safe_ptr = std::shared_ptr<Singleton>;
protected:
Singleton() = default;
~Singleton() = default;
public:
static safe_ptr get_instance() {
if (_instance == nullptr) {
std::unique_lock<std::mutex> lk(_mtx);
if (_instance == nullptr) {
//防止当一个进程退出后,释放锁,另一个进程也在等待锁拿到后进入,而多创建一个实例
_instance.reset(new Singleton());
}
}
return _instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static safe_ptr _instance;
static std::mutex _mtx;
};
std::shared_ptr<Singleton> Singleton::_instance = nullptr;
std::mutex Singleton::_mtx;
//线程安全资源安全版本2
class Singleton {
using safe_ptr = std::shared_ptr<Singleton>;
protected:
Singleton() = default;
~Singleton() = default;
public:
static safe_ptr get_instance() {
std::call_once(_flag, []()
{
_instance.reset(new Singleton());
});
return _instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static safe_ptr _instance;
static std::once_flag _flag;
};
std::shared_ptr<Singleton> Singleton::_instance = nullptr;
std::once_flag Singleton::_flag;
//模板版本
template<class Derived>
class Singleton{
public:
template<class ...Args>
static Derived& get_Instance(const Args& ...args);
protected:
Singleton() =default;
~Singleton() =default;
private:
static std::shared_ptr<Derived> _Instance;
static std::once_flag _flag;
}
template<class Derived>
template<class ...Args>
static Derived& get_Instance(const Args& ...args){
std::call_once(_flag,[](auto ...args){
_Instance.reset(new Derived(args...))
,args...});
return *_Instance;
}
template<class Derived>
std::shared_ptr<Derived> Singleton<Derived>::_Instance = nullptr;
template<class Derived>
std::once_flag Singleton<Derived>::_flag;
class A:public Singleton<A>
{
friend class Singleton<derivedA>;
private:
int val;
derived(int v):
val(v){}
public:
constexpr
int get_val() const noexcept { return val; }
}