单例模式
需要注意一点,如果使用的是指针类型的成员变量,需要对指针进行释放。
单例,就是整个进程中只有一个对象!这个对象呢有一些特殊的值需要保存,还有一些特殊的方法。
1.懒汉模式和饿汉模式的实现?
-
懒汉式:系统运行中,实例并不存在,只有当需要使用到时才进行创建。需要考虑线程安全
-
以时间换空间,适用于访问量小的时候。
-
实现1:普通的懒汉单例模式(线程不安全)
-
实现2:加锁的懒汉单例模式(线程安全)
-
SingleInstance *&SingleInstance::GetInstance() { // 这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁, // 避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。 if (m_SingleInstance == NULL) { std::unique_lock<std::mutex> lock(m_Mutex); // 加锁 if (m_SingleInstance == NULL) { m_SingleInstance = new (std::nothrow) SingleInstance; } } return m_SingleInstance; }
-
-
-
饿汉式:系统一运行,就初始化创建实例,当需要用到时候,直接调用即可。本身就是线程安全
-
以空间换时间,适用于访问量大的时候,或者线程数多的情况
-
实现1:static成员变量类外初始化,在main函数之前就被执行了
-
#include <iostream> class test { public: static test &get_instance(); static test &delete_instance(); public: test() { printf("tttt\n"); } static test *instance_; }; test *test::instance_ = new test(); test &test::get_instance() { return *instance_; } test &test::delete_instance() { if (instance_ != nullptr) { delete instance_; instance_ = nullptr; } } int main() { test::get_instance(); }
-
-
2.c++11以后的单例模式实现?
推荐使用内部静态变量的方式实现懒汉式的单例。
[C++11标准针对局部静态对象的构造能保证线程安全,如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束]。
注意点:
- 构造函数设置成private。
- 拷贝构造函数、赋值运算符禁用。
#include <memory>
#include <mutex>
template <typename T>
class Singleton {
public:
template <typename... ArgTypes>
static T* GetInstance(ArgTypes&&... args) {
if (nullptr == instance_) {
std::call_once(once_f_, [&]() { Singleton::instance_.reset(new T()); }); //reset是unique_ptr的方法,改变原始指针的指向
}
return instance_.get();
}
static T* GetInstance() {
if (nullptr == instance_) {
std::call_once(once_f_, [&]() { Singleton::instance_.reset(new T()); });
}
return instance_.get();
}
private:
Singleton();
Singleton(const Singleton& rhs) = delete;
Singleton& operator=(const Singleton& rhs) = delete;
private:
static std::unique_ptr<T> instance_; //唯一,不允许拷贝
static std::once_flag once_f_;
};
template <typename T>
std::unique_ptr<T> Singleton<T>::instance_ = nullptr;
template <typename T>
std::once_flag Singleton<T>::once_f_;
希望单例模式承担一些全局属性的存放和方法的集合,所以最好是提供一些get、set方法。
#include "Singleton.h"
#include "demo.h"
class Msg {
public:
void set(const std::string& val) { msg_ = val; }
std::string& get() { return msg_; }
void show_msg() { std::cout << msg_ << std::endl; }
private:
std::string msg_;
};
int main() {
Singleton<Msg>::GetInstance()->set("demo!");
Singleton<Msg>::GetInstance()->show_msg();
return 0;
}