单例不能用全局变量代替,因其不满足延迟初始化、全局唯一和线程安全三要素;C++11起推荐用local static实现,简洁且线程安全。
全局变量在多线程环境下不安全,且无法控制初始化时机——static局部变量在 C++11 起才保证线程安全的首次初始化,而全局对象的构造顺序跨编译单元不可控,容易引发 undefined behavior。单例的核心诉求是「延迟初始化 + 全局唯一 + 线程安全」,这三点全局变量一个都做不到。
利用函数内 static 变量的“首次调用时初始化”和“C++11 标准保证的线程安全”特性,代码极简且无锁:
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // ✅ 线程安全,仅首次调用构造
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() = default; // 可加日志或资源初始化
};
注意点:
getInstance() 必须返回引用(Singleton&),返回值会触发拷贝,破坏单例语义private,防止外部 new 或直接实例化getInstance(),可能触发静态初始化顺序问题只有在必须延迟析构(比如依赖其他单例销毁后才释

class Singleton {
public:
static Singleton& getInstance() {
static std::unique_ptr instance;
if (!instance) {
instance = std::make_unique();
}
return *instance;
}
private:
Singleton() = default;
~Singleton() = default; // 可加清理逻辑
};
隐患:
std::abort()),~Singleton() 可能不被调用早期为兼容 C++03 手写双重检查锁定(Double-Checked Locking Pattern),现在完全没必要。它要求:
std::atomic 存储指针(裸指针 + volatile 在 C++11 后无效)load() 都需指定内存序(如 memory_order_acquire)new 操作必须确保构造完成后再发布指针,否则其他线程可能看到未初始化对象哪怕抄对了,也比 local static 多出锁开销和复杂度。C++11 标准明确支持 local static 的线程安全初始化,这是标准给出的正解。
真正要注意的是:单例不是银弹。它的全局状态、隐式依赖和测试困难性,在大型项目中往往比实现本身更伤人。