马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
单例模式,其中对象是由_pInstance指针来保存的,而在利用单例设计模式的过程中,也难免会碰到内存泄漏的题目。那么是否有一个方法,可以让对象自动释放,而不需要程序员自己手动去释放呢? ——嵌套类
5.1、内存泄漏的检测工具valgrind
安装
- sudo apt install valgrind
复制代码 利用
[外链图片转存中…(img-Onqi9PtX-1728058419413)]
5.2、单例模式自动释放的四种方法 & 多线程
1、友元类
[外链图片转存中…(img-yl7twkoI-1728058419413)]
[外链图片转存中…(img-epIiJsLR-1728058419414)]
- #include <iostream>
- using std::cout;
- using std::endl;
- class Singleton
- {
- friend class AutoRelease;
- public:
- static Singleton *getInstance()
- {
- if(nullptr == _pInstance)
- {
- _pInstance = new Singleton();
- }
- return _pInstance;
- }
- static void destroy()
- {
- if(_pInstance)
- {
- delete _pInstance;
- _pInstance =nullptr;
- }
- }
- private:
- Singleton()
- {
- cout << "Singleton()" << endl;
- }
- ~Singleton()
- {
- cout << "~Singleton()" << endl;
- }
- private:
- static Singleton *_pInstance;
- };
- Singleton *Singleton::_pInstance = nullptr;
- class AutoRelease
- {
- public:
- AutoRelease()
- {
- cout << "AutoRelease()" << endl;
- }
- ~AutoRelease()
- {
- cout << "~AutoRelease()" << endl;
- if(Singleton::_pInstance)
- {
- delete Singleton::_pInstance;
- Singleton::_pInstance =nullptr;
- }
- }
- };
- int main(int argc, char **argv)
- {
- Singleton *ps1 = Singleton::getInstance();
- AutoRelease ar;//栈对象
- /* ps1->destroy(); */
- return 0;
- }
复制代码 2、内部类 + 静态数据成员
[外链图片转存中…(img-oCRKHufV-1728058419414)]
- 若_ar界说为类成员,则会死锁:
- new Singleton(),导致_ar在创建的单例堆对象内部,无法使其自动创建&析构(析构自身前,进行delete _pInstance)
- 应将_ar界说为static
- [外链图片转存中…(img-8lWGqW65-1728058419414)]
- #include <iostream>
- using std::cout;
- using std::endl;
- // 2、内部类 + 静态数据成员
- class Singleton
- {
- public:
- static Singleton *getInstance()
- {
- if (_pInstance == nullptr)
- {
- _pInstance = new Singleton(); // 构造函数
- // _ar;
- }
- return _pInstance;
- }
- static void destroy()
- {
- if (_pInstance)
- {
- delete _pInstance;
- _pInstance = nullptr;
- }
- }
- private:
- class AutoRelease
- {
- public:
- AutoRelease()
- {
- cout << "AutoRelease()" << endl;
- }
- ~AutoRelease()
- {
- cout << "~AutoRelease()" << endl;
- if (_pInstance)
- {
- delete _pInstance;
- _pInstance = nullptr;
- }
- }
- };
- private:
- Singleton()
- {
- cout << "Singleton()" << endl;
- }
- ~Singleton()
- {
- cout << "~Singleton()" << endl;
- }
- private:
- static Singleton *_pInstance; // 前向声明;定义为static,位于全局静态区(不属于本类!)
- static AutoRelease _ar; // 前向声明;对象数据成员, _ar不能存在堆上,否则死锁;定义为static,位于全局静态区(不属于本类!)
- };
- Singleton *Singleton::_pInstance = nullptr; // 静态对象必须在类外进行正式声明!
- Singleton::AutoRelease Singleton::_ar; // 静态对象必须在类外进行正式声明!
- int main(int argc, char **argv)
- {
- Singleton *ps1 = Singleton::getInstance();
- /* Singleton::AutoRelease ar;//栈对象 */
- /* ps1->destroy(); */
- return 0;
- }
- /*
- AutoRelease()
- Singleton()
- ~AutoRelease()
- ~Singleton()
- */
复制代码 采用模板
- #ifndef __WD_TEMPLATE_SINGLETON_H__
- #define __WD_TEMPLATE_SINGLETON_H__
- #include <iostream>
- using std::cout;
- using std::endl;
- #if 0
- class Singleton
- {
- public:
- static Point *getInstance(int ix, int iy)
- {
- if(nullptr == _pInstance)
- {
- _pInstance = new Point(ix, iy);
- _ar;//为了在模板参数推导时创建ar对象
- }
- return _pInstance;
- }
- };
- #endif
- template <class T>
- class Singleton
- {
- public:
- template <class... Args>
- static T *getInstance(Args... args)
- {
- if (nullptr == _pInstance)
- {
- _pInstance = new T(args...);
- _ar; // 为了在模板参数推导时创建ar对象
- }
- return _pInstance;
- }
- private:
- class AutoRelease
- {
- public:
- AutoRelease()
- {
- cout << "AutoRelease()" << endl;
- }
- ~AutoRelease()
- {
- cout << "~AutoRelease()" << endl;
- if (_pInstance)
- {
- delete _pInstance;
- _pInstance = nullptr;
- }
- }
- };
- private:
- Singleton()
- {
- cout << "Singleton()" << endl;
- /* _ar; */
- }
- ~Singleton()
- {
- cout << "~Singleton()" << endl;
- }
- private:
- static T *_pInstance;// 前向声明;定义为static,位于全局静态区(不属于本类!)
- static AutoRelease _ar;// 前向声明;对象数据成员, _ar不能存在堆上,否则死锁;定义为static,位于全局静态区(不属于本类!)
- };
- template <class T>
- T *Singleton<T>::_pInstance = nullptr; // 静态对象必须在类外进行正式声明!
- template <class T>
- typename Singleton<T>::AutoRelease Singleton<T>::_ar; // 静态对象必须在类外进行正式声明! // typename表名是一个类型
- #endif
复制代码
- Test.cpp
- #include "Singleton.h"
- #include <iostream>
- using std::cout;
- using std::endl;
- class Point
- {
- public:
- Point(int ix = 0, int iy = 0)
- : _ix(ix)
- , _iy(iy)
- {
- cout << "Point(int = 0,int = 0)" << endl;
- }
- void print() const
- {
- cout << "(" << _ix
- << "," << _iy
- << ")" << endl;
- }
- ~Point()
- {
- cout << "~Point()" << endl;
- }
- private:
- int _ix;
- int _iy;
- };
-
- int main()
- {
- Point *pt1 = Singleton<Point>::getInstance(1, 2);
- Point *pt2 = Singleton<Point>::getInstance(3, 4);
- pt1->print();
- pt2->print();
- cout << "p1 = " << pt1 << endl
- << "p2 = " << pt2 << endl;
- return 0;
- }
复制代码
3、饿汉模式 + atexit
atexit
[外链图片转存中…(img-M9pmTrsb-1728058419415)]
- #include <stdlib.h>
- #include <iostream>
- using std::cout;
- using std::endl;
- void func()
- {
- cout << "void func()" << endl;
- }
- void test()
- {
- atexit(func); // atexit: 进程正常结束时候,注册的func会被执行,注册几次就会执行几次
- atexit(func);
- atexit(func);
- atexit(func);
- atexit(func);
- }
- int main(int argc, char **argv)
- {
- cout << "start test..." << endl;
- test();
- cout << "finish test..." << endl;
- return 0;
- }
- /*
- start test...
- finish test...
- void func()
- void func()
- void func()
- void func()
- void func()
- */
复制代码 饿汉模式 + atexit
[外链图片转存中…(img-tBQqgF0g-1728058419415)]
[外链图片转存中…(img-ruQk952y-1728058419415)]
- #include <stdlib.h>
- #include <iostream>
- using std::cout;
- using std::endl;
- // 3、atexit + 饿汉模式
- class Singleton
- {
- public:
- static Singleton *getInstance()
- {
- // 在多线程情况下,是不安全的
- if (_pInstance == nullptr)
- {
- _pInstance = new Singleton(); // 构造函数
- atexit(destroy); // 使用atexit:注册函数destroy一次, 当进程正常结束后,会调用一次注册的函数destroy
- } else {
- cout << "_pInstance != nullptr" << endl;
- }
- return _pInstance;
- }
- static void destroy()
- {
- if (_pInstance)
- {
- delete _pInstance;
- _pInstance = nullptr;
- }
- }
- private:
- Singleton()
- {
- cout << "Singleton()" << endl;
- }
- ~Singleton()
- {
- cout << "~Singleton()" << endl;
- }
- private:
- static Singleton *_pInstance;
- };
- /* Singleton *Singleton::_pInstance = nullptr; //饱(懒)汉模式, 问题:多线程下,单例模式失效;*/
- Singleton *Singleton::_pInstance = getInstance(); // 饿汉模式,可解决多线程不安全问题
- void *func1(void *arg)
- {
- Singleton::getInstance();
- }
- void *func2(void *arg)
- {
- Singleton::getInstance();
- }
- void *func3(void *arg)
- {
- Singleton::getInstance();
- }
- int main(int argc, char **argv)
- {
- Singleton *ps1 = Singleton::getInstance();
- // 饱(懒)汉模式下,多线程不安全;-- 解决:使用饿汉模式
- // pthread_t th1, th2, th3;
- // pthread_create(&th1, nullptr, func1, nullptr);
- // pthread_create(&th2, nullptr, func2, nullptr);
- // pthread_create(&th3, nullptr, func3, nullptr);
- return 0;
- }
复制代码 4、多线程场景:pthread_once + atexit
[外链图片转存中…(img-MvIJXvC9-1728058419415)]
- #include <pthread.h>
- #include <stdlib.h>
- #include <iostream>
- using std::cout;
- using std::endl;
- //4、atexit + pthread_once
- //有平台问题,只能在Linux下使用
- class Singleton
- {
- public:
- static Singleton *getInstance()
- {
- //当第一个参数是某个固定值的时候,可以保证第一个参数只会被
- //调用一次 call_once
- pthread_once(&_once, init);
- return _pInstance;
- }
- static void init()
- {
- _pInstance = new Singleton();//构造函数
- atexit(destroy);
- }
- static void destroy()
- {
- if(_pInstance)
- {
- delete _pInstance;
- _pInstance = nullptr;
- }
- }
- private:
- Singleton()
- {
- cout << "Singleton()" << endl;
- }
- ~Singleton()
- {
- cout << "~Singleton()" << endl;
- }
- private:
- static Singleton *_pInstance;
- static pthread_once_t _once;
- };
- Singleton *Singleton::_pInstance = nullptr; //饱(懒)汉模式
- /* Singleton *Singleton::_pInstance = getInstance();//饿汉模式 */
- pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;
- int main(int argc, char **argv)
- {
- Singleton *ps1 = Singleton::getInstance();
- return 0;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |