野百合也有春天

导航

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;
}

posted on   flydream  阅读(478)  评论(0编辑  收藏  举报

努力加载评论中...
点击右上角即可分享
微信分享提示