网站建设电话销售不被挂断,wordpress 上传rar,wordpress播放直播,网址建站单例模式#xff0c;其中对象是由_pInstance指针来保存的#xff0c;而在使用单例设计模式的过程中#xff0c;也难免会遇到内存泄漏的问题。那么是否有一个方法#xff0c;可以让对象自动释放#xff0c;而不需要程序员自己手动去释放呢#xff1f; ——嵌套类
5.1、内…单例模式其中对象是由_pInstance指针来保存的而在使用单例设计模式的过程中也难免会遇到内存泄漏的问题。那么是否有一个方法可以让对象自动释放而不需要程序员自己手动去释放呢 ——嵌套类
5.1、内存泄漏的检测工具valgrind
安装
sudo apt install valgrind使用
[外链图片转存中…(img-Onqi9PtX-1728058419413)]
5.2、单例模式自动释放的四种方法 多线程
1、友元类
[外链图片转存中…(img-yl7twkoI-1728058419413)]
[外链图片转存中…(img-epIiJsLR-1728058419414)]
#include iostreamusing 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 iostreamusing 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()*/采用模板
Singleton.h
#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... Argsstatic 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 *SingletonT::_pInstance nullptr; // 静态对象必须在类外进行正式声明template class T
typename SingletonT::AutoRelease SingletonT::_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 SingletonPoint::getInstance(1, 2);Point *pt2 SingletonPoint::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 iostreamusing 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 iostreamusing 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 iostreamusing std::cout;
using std::endl;//4、atexit pthread_once
//有平台问题只能在Linux下使用class Singleton
{
public:static Singleton *getInstance(){//当第一个参数是某个固定值的时候可以保证第一个参数只会被//调用一次 call_oncepthread_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;
}