//单例模式,也带点过度设计的无聊美感 //单例模式是一种强制性的约束,一个物体全局只有唯一实例 //在C/cpp中完全可以用全局变量实现(C++允许在函数外构建对象实例) //当然java就比较麻烦了,java不允许出现全局变量,单例模式似乎是唯一选择 //单例模式的核心是C系语言静态变量的特性 //所有的静态变量的生命周期都是全局的 //C系语言中有三种静态变量,分别是类作用域,局部作用域和全局作用域 //类作用域的静态变量所有的实例中只有唯一的副本,并且在访问的时候访问的是唯一的静态变量 //局部作用域的静态变量,作用域只有局部,但是生命周期是全局(由于不进行链接,因此不会创建额外的副本) //全局静态变量的作用域是全局,但是只有内部链接性,即每一个包含头文件的的cpp文件中有一个独立的副本 #include #include #include #include //这个单例模式是内存安全的,在于cpp11之后现代cpp的static变量的构建是内存安全的 class signal { protected: signal()=default; signal(const signal&)=delete; signal(signal&&)=delete; signal& operator=(const signal&)=delete; signal& operator=(signal&&)=delete; public: static signal& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本 { static signal data; return data; } }; //懒汉式,以及cpp11之前的单例模式 //使用双检锁保证初始化顺序 class thread_signal { private: //C++11之前没有这些类就需要使用boost实现 static std::atomic instance; static std::mutex mtx; public: static thread_signal* get() { thread_signal* data=instance.load(std::memory_order_acquire); if(data==nullptr) { std::lock_guard lock(mtx); data=instance.load(std::memory_order_relaxed); //重新加载一次防止在前面的判断过程中已经被改变,由于在锁的范围,直接用宽松内存序就好 if(data==nullptr) { data=new thread_signal(); instance.store(data,std::memory_order_relaxed); } } return data; //由于初始化是唯一的因此只会初始化一次,不会出现改变 } }; //每线程单例 class signal_thread_local { protected: signal_thread_local(int _i):i(_i){}; signal_thread_local(const signal_thread_local&)=delete; signal_thread_local(signal_thread_local&&)=delete; signal_thread_local& operator=(const signal_thread_local&)=delete; signal_thread_local& operator=(signal_thread_local&&)=delete; public: int i; static signal_thread_local& get() //核心是引用返回的是内部构建的局部变量而不是一个copy后的副本 { thread_local signal_thread_local data(0); //构建线程作用域的单例 return data; } }; void fun(int j) { signal_thread_local& re1=signal_thread_local::get(); re1.i=re1.i+j; signal_thread_local& re2=signal_thread_local::get(); std::cout<