在C++11及后续标准中,Meyer’s Singleton是一种极其简洁且线程安全的单例模式实现,其核心依赖于C++11标准对局部静态变量初始化的线程安全保证。以下是完整实现及解析:
完整代码实现
#include <iostream>
class Singleton {
private:
// 1. 私有构造函数:禁止外部实例化
Singleton() {
std::cout << "Singleton 实例被创建" << std::endl;
}
// 2. 私有析构函数(可选):控制销毁逻辑
~Singleton() {
std::cout << "Singleton 实例被销毁" << std::endl;
}
// 3. 禁用拷贝构造和赋值运算:防止单例被复制
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator=(const Singleton&) = delete; // 禁止赋值运算
public:
// 4. 全局访问点:返回单例实例的引用
static Singleton& getInstance() {
// 局部静态变量:C++11保证其初始化是线程安全的
// 首次调用时初始化,且仅初始化一次
static Singleton instance;
return instance;
}
// 示例成员函数:单例的业务逻辑
void doSomething() {
std::cout << "Singleton 执行操作" << std::endl;
}
};
// 使用示例
int main() {
// 第一次调用:触发实例初始化
Singleton& s1 = Singleton::getInstance();
s1.doSomething();
// 第二次调用:返回已存在的实例(不会重新初始化)
Singleton& s2 = Singleton::getInstance();
s2.doSomething();
// 验证两个引用指向同一个实例
std::cout << "s1 地址: " << &s1 << std::endl;
std::cout << "s2 地址: " << &s2 << std::endl;
return 0;
}
核心特性解析
-
线程安全的初始化
C++11标准规定:局部静态变量的初始化在多线程环境下是线程安全的。当多个线程同时首次调用getInstance()时,系统会保证只有一个线程执行instance的初始化,其他线程会等待初始化完成。这避免了传统懒汉模式中“双重检查锁定”的复杂实现。 -
延迟初始化
实例仅在首次调用getInstance()时才被创建,而非程序启动时,节省了不必要的资源消耗(对比饿汉模式)。 -
自动销毁
单例实例instance作为局部静态变量,其生命周期与程序一致:在首次初始化后持续存在,直到程序结束时自动调用析构函数销毁,无需手动管理内存(避免内存泄漏)。 -
防止复制
通过=delete显式禁用拷贝构造函数和赋值运算符,确保无法通过复制创建新的实例,严格保证“唯一性”。
输出结果
Singleton 实例被创建
Singleton 执行操作
Singleton 执行操作
s1 地址: 0x7f8a1b2c3d4e
s2 地址: 0x7f8a1b2c3d4e // 地址相同,证明是同一个实例
Singleton 实例被销毁 // 程序结束时自动销毁
适用场景
- 需要全局唯一实例,且实例创建成本较高(适合延迟初始化)。
- 多线程环境下,需要线程安全的单例实现。
- 希望代码简洁,避免手动加锁或动态内存管理的场景。
注意事项
- 标准版本:仅在C++11及以上标准中保证线程安全。C++03及更早版本中,局部静态变量的初始化不保证线程安全,需谨慎使用。
- 析构顺序:若多个单例存在依赖关系,其析构顺序可能与初始化顺序相反,需避免析构时访问已销毁的依赖对象。
Meyer’s Singleton凭借其简洁性和安全性,成为C++11及以后版本中最推荐的单例实现方式之一。
731

被折叠的 条评论
为什么被折叠?



