C++11以前需要双重检查,但是双重检查也是不安全的所以需要加锁;C++11以后,规定了local static在多线程条件下的初始化行为,要求编译器保证了内部静态变量的线程安全性.也就是说local static变量会在编译期初始化,我们可以利用这一特性完成单例.
#include
#include
class Singleton {
private:
Singleton() {
std::cout << "构造函数" << std::endl;
};
~Singleton() {
std::cout << "析构函数" << std::endl;
};
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
//返回local static的引用
static Singleton instance;
return instance;
}
};
int main(void)
{
for (int i = 0; i < 10; ++i) {
std::thread([]() {
std::cout << &Singleton::getInstance() << std::endl;
}).join();
}
std::cout << &Singleton::getInstance() << std::endl;
return 0;
}
这样,单例类就算完成了,这种方式称为Meyers’ Singleton.在简单需求情况下这种方式完全可以,不过遇到多个单例相互依赖需要按顺序析构的情况就有问题了.
代码来自modern C++ design,github地址:https://github.com/dutor/loki
利用模板参数来设置单例的属性,包括构造策略,析构策略,线程策略;还可以继承对应的类来实现自己的策略
template <
typename T,
template <class> class CreationPolicy = CreateUsingNew,
template <class> class LifetimePolicy = DefaultLifetime,
template <class> class ThreadingModel = SingleThreaded >
class SingletonHolder {
public:
static T& Instance();
private:
// Helpers
static void MakeInstance();
static void C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
// Protection
SingletonHolder();
// Data
typedef typename ThreadingModel<T*>::VolatileType PtrInstanceType;
static PtrInstanceType pInstance_;
static bool destroyed_;
};
这是一种较为复杂的写法,可以设置单例的属性;Facebook的folly用的也是这种手法.不过呢,编程应该以简单为原则,不要过度优化你的程序!