一般来说,程序退出的时候,所有的资源都被回收,但是在使用检测内存泄露的工具比如valgrind时会被检测出来,可以理解为这是一种“假的内存泄漏”。为此,这里分别使用三种方法来避免这个问题。
方案一:嵌套类+静态对象
代码实现:
1 #include <iostream>
2 using std::cout;
3 using std::endl;
4
5 class Signalton
6 {
7 class AutoRelease
8 {
9 public:
10 AutoRelease()
11 {
12 cout<<"AutoRelease()"<<endl;
13 }
14
15 ~AutoRelease()
16 {
17 if(_pInstance)
18 {
19 delete _pInstance;
20 cout<<"~AutoRelease()"<<endl;
21 }
22 }
23 };
24 public:
25 static Signalton * getInstance()
26 {
27 if(_pInstance==nullptr)
28 {
29 _pInstance=new Signalton();
30 }
31 return _pInstance;
32 }
33
34 void destroy()
35 {
36 if(_pInstance)
37 delete _pInstance;
38 }
39
40 void print()const
41 {
42 cout<<"void print()const"<<endl;
43 }
44
45
46 private:
47 Signalton(){cout<<"Signal()"<<endl;}
48 ~Signalton(){cout<<"~Signal()"<<endl;}
49
50 private:
51 static Signalton * _pInstance;
52 static Signalton _autoRelease;
53 };
54
55 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
56 Signalton *Signalton:: _pInstance=Signalton::getInstance();//饱汉模式
57
58 Signalton Signalton:: _autoRelease;
59
60 int main()
61 {
62 Signalton * p=Signalton::getInstance();
63 p->print();
64
65 // p->destroy();
66
67 return 0;
68 }
方案二:atexit + 静态对象
#include <stdlib.h>
int atexit(void (*function)(void));
功能:注册终止函数,即main函数结束之后调用。
用法:接受一个无参的函数。exit调用这些注册函数的顺序与它们登记时候的顺序相反。同一个函 数如若登记多次,则也会被调用多次。
代码实现:
1 #include <stdlib.h>
2 #include <iostream>
3 using std::cout;
4 using std::endl;
5
6 class Signalton
7 {
8 public:
9 static Signalton * getInstance()
10 {
11 if(_pInstance==nullptr)
12 {//因为只能新建对象一次,并所以只回收一次,因此在第一创建对象的时候就注册
13 _pInstance=new Signalton();
14 atexit(destroy);//在新建对象时,注册结束函数
15 }
16 return _pInstance;
17 }
18
19 static void destroy()
20 {
21 if(_pInstance)
22 delete _pInstance;
23 }
24
25 void print()const
26 {
27 cout<<"void print()const"<<endl;
28 }
29
30
31 private:
32 Signalton(){cout<<"Signal()"<<endl;}
33 ~Signalton(){cout<<"~Signal()"<<endl;}
34
35 private:
36 static Signalton * _pInstance;
37 };
38
39 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
40 Signalton *Signalton:: _pInstance=Signalton::getInstance();//饱汉模式
41
42 int main()
43 {
44 Signalton * p=Signalton::getInstance();
45 p->print();
46
47 // p->destroy();
48
49 return 0;
50 }
方案三:atexit + pthread_once
#include <pthread>
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));
功能:本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在多线程执行序列中仅执行一次。使用该函数保证了多线程安全。
1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 class Signalton
8 {
9 public:
10 static Signalton * getInstance()
11 {
12 pthread_once(&_once,init);
13 return _pInstance;
14 }
15 //init若不被声明为静态类型,则第一个参数为this指针,便不满足pthread_once传入无参函数的要求
16 static void init()
17 {
18 _pInstance=new Signalton();
19 atexit(destroy);
20 }
21
22 static void destroy()
23 {
24 if(_pInstance)
25 delete _pInstance;
26 }
27
28 void print()const
29 {
30 cout<<"void print()const"<<endl;
31 }
32
33
34 private:
35 Signalton(){cout<<"Signal()"<<endl;}
36 ~Signalton(){cout<<"~Signal()"<<endl;}
37
38 private:
39 static Signalton * _pInstance;
40 static pthread_once_t _once;
41 };
42
43 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
44 Signalton *Signalton:: _pInstance=nullptr;//饱汉模式
45 pthread_once_t Signalton::_once=PTHREAD_ONCE_INIT;
46
47 int main()
48 {
49 Signalton * p=Signalton::getInstance();
50 p->print();
51
52 // p->destroy();
53
54 return 0;
55 }
总结
前两种方法都是可以跨平台的,第三种方法具有平台相关性。