singleton的内存泄漏及线程安全性问题
原文链接:
http://patmusing.blog.163.com/blog/static/135834960201002322226231/
一、最简单的实现方式
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 | // Singleton.h // C++:最简单的方式实现Singleton设计模式 #pragma once #include <string> #include <iostream> using namespace std; class Singleton { private : Singleton() // private构造函数 { cout << "Singleton::Constructor" << endl; } static Singleton* sg; // 私有静态变量,其类型为Singleton* // 形如Singleton sg;这样的声明会出编译时错误 public : static Singleton* getInstance() // public成员函数getInstance() { cout << "Singleton::getInstance" << endl; if (!sg) { sg = new Singleton(); // (1)在这个地方new了一个对象,但是在什么地方delete呢? } return sg; } }; |
1 2 3 4 5 6 7 8 9 10 11 | #include "stdafx.h" #include "Singleton.h" // 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象 Singleton* Singleton::sg = 0; int main( void ) { Singleton *sg = Singleton::getInstance(); return 0; } |
语句(1)中new了一个对象,但没有被delete,因此肯定会造成内存泄漏。
二、使用auto_ptr来解决内存泄漏问题
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 | // Singleton.h #include <memory> #include <string> #include <iostream> using namespace std; // C++:使用auto_ptr实现Singleton设计模式 class Singleton { private : Singleton() // private构造函数 { cout << "Singleton::Constructor" << endl; } // 私有静态变量,其类型为auto_ptr<Singleton> static auto_ptr<Singleton> sg; public : // public成员函数getInstance() static auto_ptr<Singleton> getInstance() // 返回类型为auto_ptr<Singleton> { cout << "Singleton::getInstance" << endl; if (!sg.get()) // 判断sg所指的对象是否为空 { // 此处不能直接写成auto_ptr<Singleton> sg(new Singleton); auto_ptr<Singleton> temp( new Singleton); sg = temp; } return sg; } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include "stdafx.h" // Singleton.cpp:测试Singleton的代码 #include "Singleton.h" // 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象 auto_ptr<Singleton> Singleton::sg; int main( void ) { // singleton就是我们需要的对象 auto_ptr<Singleton> singleton(Singleton::getInstance()); return 0; } |
三、基于模块的方法实现:
进一步地,我们还可以将Singleton类,写成模板类,这样就可以更加灵活了。为此,我们另外增加一个类Student用来测试,Singleton模板类。
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 | //Singleton.h #include <memory> #include <string> #include <iostream> using namespace std; class Student { public : Student( const string name = "Andrew" , const int age = 7) : name(name), age(age) { cout << "constructor..." << endl; } void print_info() const { cout << "Name: " << name << ", Age: " << age << endl; } private : string name; int age; }; // Singleton模板类 template < typename T> class Singleton { private : Singleton() // private构造函数 { cout << "Singleton::Constructor" << endl; } static auto_ptr<T> sg; // 私有静态变量,其类型为auto_ptr<T> public : static auto_ptr<T> getInstance() // public成员函数getInstance() { // 返回类型为auto_ptr<T> cout << "Singleton::getInstance" << endl; if (!sg.get()) // 判断sg所指的对象是否为空 { // 此处不能直接写成auto_ptr<T> sg(new T); auto_ptr<T> temp( new T); sg = temp; } return sg; } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Singleton.cpp 测试代码 #include "stdafx.h" #include "Singleton.h" // 用下面的方式对静态私有成员变量sg进行初始化,此时sg不指向任何对象 auto_ptr<Student> Singleton<Student>::sg; int main( void ) { auto_ptr<Student> singleton(Singleton<Student>::getInstance()); singleton->print_info(); return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步