C++11起Meyers Singleton(局部静态变量版)是线程安全、简洁且生命周期自动管理的单例实现;标准保证其首次初始化原子性,编译器自动生成同步机制,无需手动加锁或指针管理。
直接说结论:C++11 及以后,用 Meyers Singleton(即局部静态变量版本)是线程安全、简洁且无需手动管理生命周期的单例写法——标准明确保证其初始化的线程安全性。
Meyers Singleton 天然线程安全?C++11 标准规定:函数内局部静态变量的首次初始化是原子的,且编译

__cxa_guard_acquire 等)。这意味着多个线程同时首次调用 instance(),也只会有一个执行构造,其余阻塞等待,无需 std::mutex 或双重检查锁(DCLP)。
常见错误是误以为“静态局部变量 = 不加锁就可能竞争”,这是 C++11 之前的老认知,已过时。
getInstance() 的正确写法与关键细节核心就是把单例对象声明为函数局部静态变量,并返回引用:
class Logger {
public:
static Logger& instance() {
static Logger instance_; // ✅ C++11 线程安全初始化
return instance_;
}
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
private:
Logger() = default; // 可设为 private,但不必显式 inline
};
Logger&(引用),不能返回值(否则触发拷贝/移动,破坏单例语义)static Logger instance_; 必须在函数体内定义,不能提至全局或类静态成员——那是老式写法,需手动同步atexit 或管理老写法如 static Logger* instance_ = nullptr; + if (!instance_) instance_ = new Logger; 有多个隐患:
atexit 竞争、以及 static 对象析构时调用单例的崩溃风险(静态析构顺序不确定)Logger 析构函数会被自动调用template static T& instance() )真正要注意的不是“怎么加锁”,而是别在 C++11+ 环境里倒退回去手写锁或指针管理——局部静态变量的线程安全是语言级保障,不是巧合。