网站建设奖项,怎样免费安装wordpress,织梦网站流动广告代码,阿里巴巴国际贸易网站推广工具一、介绍
1.动机
在软件系统中#xff0c;经常有这样一些特殊的类#xff0c;必须保证它们在系统中只存在一个实例#xff0c;才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器#xff0c;提供一种机制来保证一个类只有一个实例?
这应该是类设计者的…一、介绍
1.动机
在软件系统中经常有这样一些特殊的类必须保证它们在系统中只存在一个实例才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器提供一种机制来保证一个类只有一个实例?
这应该是类设计者的责任而不是使用者的责任。 2.定义
保证一个类仅有一个实例并提供一个该实例的全局访问点。——GOF 3.结构图 4.要点总结
Singleton模式中的实例构造器可以设置为protected以允许子类派生。Singleton模式一般不支持拷贝构造函数和Clone接口因为这有可能导致多个对象实例与Singleton模式的初衷违背。如何实现多线程环境下安全的Singleton注意对双检查锁的正确实现。 二、单例模式
1.概念
单例模式的核心在于类自身负责创建自己的唯一实例并提供一个静态方法来获取这个实例从而防止外部代码创建多个实例。
①单例模式的优点
节省资源避免频繁创建和销毁对象。方便控制资源的使用。维护数据的一致性。
②单例模式的缺点
在多线程环境下需要考虑线程安全问题。若使用锁机制可能会影响性能。 2.实现要点
单例模式的实现要点
私有化构造函数防止在外部通过构造函数直接创建对象。禁用拷贝构造和赋值运算符防止通过拷贝构造和赋值操作创建多个对象。静态变量存储类的唯一实例。公有静态方法提供一个全局访问点来获取这个实例。
单例模式分为饿汉式和懒汉式。 3.饿汉式
在程序启动时立即创建实例因此本身是线程安全的。但无论是否使用实例都会立即创建可能导致资源浪费。
饿汉式单例
class Singleton {
private:static Singleton* pSingleton;Singleton() {cout Singleton() endl;}~Singleton() {cout ~Singleton() endl;}public:Singleton(const Singleton) delete; //禁用拷贝构造函数Singleton operator(const Singleton) delete; //禁用赋值运算符static Singleton* getInstance() {return pSingleton;}static void deleteInstance() { //用于删除实例cout deleteInstance() endl;if (pSingleton) {delete pSingleton;pSingleton nullptr;}}
};
Singleton* Singleton::pSingleton new Singleton();
//直接创建实例
测试
Singleton* s1 Singleton::getInstance();
Singleton* s2 Singleton::getInstance();
cout s1 endl;
cout s2 endl;
Singleton::deleteInstance(); 4.懒汉式
程序启动时实例并不存在只有在需要使用时才会创建实例这种方式要考虑线程安全的问题。
①使用静态局部变量实现懒汉式单例
class Singleton {
private:Singleton() {cout Singleton() endl;}~Singleton() {cout ~Singleton() endl;}public:static Singleton* getInstance() {static Singleton instance; //静态局部变量return instance;}Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;};
静态局部变量存储在静态存储区只在当前函数内有效其它函数无法访问。
静态局部变量只在第一次调用时初始化生命周期从第一次初始化开始到程序结束为止。 ②使用双检查锁实现懒汉式单例
class Singleton {
private:static mutex mtx; //互斥锁static atomicshared_ptrSingleton pSingleton; //原子智能指针Singleton() {cout Singleton() endl;}public:~Singleton() { //设置为公有智能指针要调用cout ~Singleton() endl;}Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;static shared_ptrSingleton getInstance() {shared_ptrSingleton ptr pSingleton.load(); //读取if (!ptr) { //第一次检查unique_lockmutex amtx(mtx);ptr pSingleton.load(); //读取if (!ptr) { //第二次检查ptr shared_ptrSingleton(new Singleton);pSingleton.store(ptr); //存储}}return ptr;}
};
mutex Singleton::mtx;
atomicshared_ptrSingleton Singleton::pSingleton nullptr;
atomic的load和store成员函数用于以原子方式读取和存储原子变量。它们可以接受一个memory_order参数该参数用于指定在内存模型中操作的内存顺序。如果不提供则会默认使用memory_order_seq_cst这是最严格的内存顺序它保证了读取操作的顺序性和内存可见性。 ③使用call_once实现懒汉式单例
class Singleton {
private:static once_flag flag; //用于标记static shared_ptrSingleton pSingleton; //智能指针Singleton() {cout Singleton() endl;}public:~Singleton() { //设置为公有智能指针要调用cout ~Singleton() endl;}Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;static shared_ptrSingleton getInstance() {call_once(flag, [] { //最多调用一次pSingleton shared_ptrSingleton(new Singleton);});return pSingleton;}
};
once_flag Singleton::flag;
shared_ptrSingleton Singleton::pSingleton nullptr;
call_once可以让函数或代码块在多线程环境中最多只被执行一次。