导言
单例模式的自动释放是解决资源泄漏问题的关键,不同场景下可以选择不同的实现方式。下面详细解析四种典型的自动释放机制,包括其实现原理、代码示例及适用场景。
一、方式一:利用栈对象的生命周期进行管理
实现原理
利用栈对象 "出作用域自动析构" 的特性,将单例指针存储在栈对象中,当栈对象被销毁时,自动释放单例资源。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <iostream>
class Singleton { private: // 私有构造函数 Singleton() { std::cout << "Singleton 构造函数被调用" << std::endl; } // 私有析构函数 ~Singleton() { std::cout << "Singleton 析构函数被调用" << std::endl; } // 禁止拷贝和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; // 单例实例指针 static Singleton* instance; // 栈对象管理类 class AutoRelease { public: ~AutoRelease() { if (Singleton::instance != nullptr) { delete Singleton::instance; Singleton::instance = nullptr; } } };
public: // 获取单例实例 static Singleton* getInstance() { // 栈对象,生命周期结束时自动析构 static AutoRelease autoRelease; if (instance == nullptr) { instance = new Singleton(); } return instance; } };
// 初始化静态成员 Singleton* Singleton::instance = nullptr;
int main() { Singleton* s1 = Singleton::getInstance(); Singleton* s2 = Singleton::getInstance(); std::cout << "s1 地址: " << s1 << std::endl; std::cout << "s2 地址: " << s2 << std::endl; // 程序结束时,autoRelease对象析构,自动释放单例 return 0; }
|
特点分析
二、方式二:使用内部类与内部类静态对象
实现原理
通过内部类定义释放逻辑,同时在内部类中定义静态对象,利用全局静态对象在程序结束时自动析构的特性触发单例释放。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream>
class Singleton { private: // 私有构造函数 Singleton() { std::cout << "Singleton 构造函数被调用" << std::endl; } // 私有析构函数 ~Singleton() { std::cout << "Singleton 析构函数被调用" << std::endl; } // 禁止拷贝和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; // 单例实例指针 static Singleton* instance; // 内部释放类 class Deleter { public: ~Deleter() { if (Singleton::instance != nullptr) { delete Singleton::instance; Singleton::instance = nullptr; } } }; // 内部类静态对象,程序结束时自动析构 static Deleter deleter;
public: // 获取单例实例 static Singleton* getInstance() { if (instance == nullptr) { instance = new Singleton(); } return instance; } };
// 初始化静态成员 Singleton* Singleton::instance = nullptr; Singleton::Deleter Singleton::deleter;
int main() { Singleton* s = Singleton::getInstance(); return 0; }
|
特点分析
优点:释放逻辑封装在内部类中,实现清晰;静态对象在程序启动时就已创建
缺点:即使单例从未被使用,deleter 对象也会占用资源
适用场景:需要确保释放器一定存在的场景,兼容性好(支持 C++03 及以上)
三、方式三:使用 atexit () + destroyInstance ()
实现原理
利用标准库函数atexit()注册单例释放函数,当程序正常结束时,系统会自动调用所有通过atexit()注册的函数。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <iostream> #include <cstdlib> // 包含atexit()
class Singleton { private: // 私有构造函数 Singleton() { std::cout << "Singleton 构造函数被调用" << std::endl; } // 私有析构函数 ~Singleton() { std::cout << "Singleton 析构函数被调用" << std::endl; } // 禁止拷贝和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; // 单例实例指针 static Singleton* instance; // 销毁单例的静态函数 static void destroyInstance() { if (instance != nullptr) { delete instance; instance = nullptr; } }
public: // 获取单例实例 static Singleton* getInstance() { if (instance == nullptr) { instance = new Singleton(); // 注册销毁函数,程序结束时自动调用 atexit(destroyInstance); } return instance; } };
// 初始化静态成员 Singleton* Singleton::instance = nullptr;
int main() { Singleton* s = Singleton::getInstance(); return 0; }
|
特点分析
四、方式四:线程安全的实现(atexit () + destroyInstance () + pthread_once)
实现原理
结合 POSIX 线程库的pthread_once()函数确保单例初始化的线程安全性,同时使用atexit()注册释放函数,实现线程安全的自动释放。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <iostream> #include <cstdlib> #include <pthread.h>
class Singleton { private: // 私有构造函数 Singleton() { std::cout << "Singleton 构造函数被调用" << std::endl; } // 私有析构函数 ~Singleton() { std::cout << "Singleton 析构函数被调用" << std::endl; } // 禁止拷贝和赋值 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; // 单例实例指针 static Singleton* instance; // pthread_once使用的控制变量 static pthread_once_t onceControl; // 初始化单例的静态函数 static void initInstance() { instance = new Singleton(); // 注册销毁函数 atexit(destroyInstance); } // 销毁单例的静态函数 static void destroyInstance() { if (instance != nullptr) { delete instance; instance = nullptr; } }
public: // 获取单例实例,线程安全版本 static Singleton* getInstance() { // pthread_once确保initInstance只被调用一次,线程安全 pthread_once(&onceControl, initInstance); return instance; } };
// 初始化静态成员 Singleton* Singleton::instance = nullptr; pthread_once_t Singleton::onceControl = PTHREAD_ONCE_INIT;
int main() { Singleton* s = Singleton::getInstance(); return 0; }
|
编译与运行
需要链接 pthread 库:g++ -o singleton singleton.cpp -lpthread
特点分析
优点:绝对的线程安全,初始化过程原子化;自动释放资源
缺点:依赖 POSIX 线程库,Windows 平台需要特殊处理
适用场景:Linux/Unix 多线程环境,对线程安全性要求高的场景
五、五种自动释放方式对比表
实现方式 |
线程安全 |
兼容性 |
实现复杂度 |
释放时机控制 |
资源占用 |
栈对象管理 |
否 |
高 |
低 |
中 |
低 |
内部类静态对象 |
否 |
高 |
低 |
高 |
中 |
atexit () 方式 |
否 |
高 |
低 |
中 |
低 |
pthread_once 方式 |
是 |
中 |
中 |
中 |
低 |