Weak pointer的实现方法.
1
#include <assert.h>
2
#include <map>
3
#include <stdio.h>
4
5
// memory leak checker
6
struct Value
7
{
8
bool valid;
9
int line;
10
11
Value()
12
:valid(false), line(-1)
13
{}
14
15
Value(bool v, int l)
16
:valid(v), line(l)
17
{
18
}
19
};
20
21
typedef std::map<void*, Value> ContainerType;
22
ContainerType myMap;
23
24
#define mynew(x) mynew_(x, __LINE__)
25
26
void checkMemory()
27
{
28
size_t n = myMap.size();
29
//assert(n==0);
30
31
if(n>0)
32
{
33
printf("Memory leak found:\n");
34
for (ContainerType::const_iterator it=myMap.begin();
35
it!=myMap.end();++it)
36
{
37
printf("Line %d\n", it->second.line);
38
}
39
assert(0);
40
}
41
}
42
43
template <class T>
44
T* mynew_(T const &n, int line)
45
{
46
T* p = (T*)malloc(sizeof(T));
47
*p = n;
48
myMap[p]=Value(true, line);
49
return p;
50
}
51
52
void mydelete(void* p)
53
{
54
ContainerType::iterator it = myMap.find(p);
55
assert(it!=myMap.end());
56
myMap.erase(it);
57
free(p);
58
}
59
60
class AutoPtr
61
{
62
public:
63
explicit AutoPtr(int *p=0)
64
:p_(p), refCnt_(mynew(int(1))), valid_(mynew(bool(p?true:false)))
65
{}
66
67
~AutoPtr()
68
{
69
if(p_)
70
{
71
mydelete (p_);
72
}
73
74
(*refCnt_)--;
75
76
*valid_ = false;
77
78
assert(*refCnt_>=0);
79
if(*refCnt_==0)
80
{
81
mydelete(refCnt_);
82
mydelete(valid_);
83
}
84
}
85
86
bool empty() const
87
{
88
if(!*valid_)
89
assert(p_==0);
90
else
91
assert(p_!=0);
92
93
return !(*valid_);
94
}
95
private:
96
friend class WeakPtr;
97
AutoPtr(const AutoPtr&);
98
AutoPtr& operator =(const AutoPtr&);
99
100
int *p_;
101
bool *valid_;
102
int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
103
};
104
105
class WeakPtr
106
{
107
public:
108
// ctor
109
WeakPtr()
110
:p_(0), refCnt_(mynew(int(1))), valid_(mynew(bool(false)))
111
{
112
}
113
114
explicit WeakPtr(AutoPtr& p) //p must be valid
115
:p_(&p), refCnt_(p.refCnt_),valid_(p.valid_)
116
{
117
(*p_->refCnt_)++;
118
}
119
120
WeakPtr(const WeakPtr& rhs) //p must be valid
121
{
122
construct(rhs);
123
}
124
125
~WeakPtr()
126
{
127
destroy();
128
}
129
130
// get
131
bool empty() const
132
{
133
assert((*refCnt_)>=0);
134
return !(*valid_);
135
}
136
137
// operator
138
WeakPtr& operator=(const WeakPtr &rhs)
139
{
140
if(this!=&rhs)
141
{
142
destroy();
143
construct(rhs);
144
}
145
return *this;
146
}
147
148
private:
149
void destroy()
150
{
151
(*refCnt_)--;
152
153
assert((*refCnt_)>=0);
154
if(0==*refCnt_)
155
{
156
mydelete(refCnt_);
157
mydelete(valid_);
158
}
159
160
}
161
void construct(const WeakPtr &rhs)
162
{
163
p_ = rhs.p_;
164
refCnt_ = rhs.refCnt_;
165
valid_ = rhs.valid_;
166
(*refCnt_)++;
167
}
168
169
AutoPtr *p_;
170
bool *valid_;
171
int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist
172
};
173
174
void Test()
175
{
176
WeakPtr p1;
177
178
assert(p1.empty());
179
{
180
AutoPtr p(mynew(int(100)));
181
p1 = WeakPtr(p);
182
assert(!p1.empty());
183
assert(!p.empty());
184
}
185
assert(p1.empty());
186
187
//mynew(int());
188
}
189
190
void main()
191
{
192
Test();
193
checkMemory();
194
}
#include <assert.h>2
#include <map>3
#include <stdio.h>4

5
// memory leak checker6
struct Value7
{8
bool valid;9
int line;10

11
Value()12
:valid(false), line(-1)13
{}14

15
Value(bool v, int l)16
:valid(v), line(l)17
{18
}19
};20

21
typedef std::map<void*, Value> ContainerType;22
ContainerType myMap;23

24
#define mynew(x) mynew_(x, __LINE__)25

26
void checkMemory()27
{28
size_t n = myMap.size();29
//assert(n==0);30

31
if(n>0)32
{33
printf("Memory leak found:\n");34
for (ContainerType::const_iterator it=myMap.begin();35
it!=myMap.end();++it)36
{37
printf("Line %d\n", it->second.line);38
}39
assert(0);40
}41
}42

43
template <class T>44
T* mynew_(T const &n, int line)45
{46
T* p = (T*)malloc(sizeof(T));47
*p = n;48
myMap[p]=Value(true, line);49
return p;50
}51

52
void mydelete(void* p)53
{54
ContainerType::iterator it = myMap.find(p);55
assert(it!=myMap.end());56
myMap.erase(it);57
free(p);58
}59

60
class AutoPtr61
{62
public:63
explicit AutoPtr(int *p=0)64
:p_(p), refCnt_(mynew(int(1))), valid_(mynew(bool(p?true:false)))65
{}66

67
~AutoPtr()68
{69
if(p_)70
{71
mydelete (p_);72
}73

74
(*refCnt_)--;75
76
*valid_ = false;77

78
assert(*refCnt_>=0);79
if(*refCnt_==0)80
{81
mydelete(refCnt_);82
mydelete(valid_);83
}84
}85

86
bool empty() const87
{88
if(!*valid_) 89
assert(p_==0);90
else91
assert(p_!=0);92

93
return !(*valid_);94
}95
private:96
friend class WeakPtr;97
AutoPtr(const AutoPtr&);98
AutoPtr& operator =(const AutoPtr&);99

100
int *p_;101
bool *valid_;102
int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist103
};104

105
class WeakPtr106
{107
public:108
// ctor109
WeakPtr()110
:p_(0), refCnt_(mynew(int(1))), valid_(mynew(bool(false)))111
{112
}113

114
explicit WeakPtr(AutoPtr& p) //p must be valid115
:p_(&p), refCnt_(p.refCnt_),valid_(p.valid_)116
{117
(*p_->refCnt_)++;118
}119
120
WeakPtr(const WeakPtr& rhs) //p must be valid121
{122
construct(rhs);123
}124

125
~WeakPtr()126
{127
destroy();128
}129

130
// get131
bool empty() const132
{133
assert((*refCnt_)>=0);134
return !(*valid_);135
}136

137
// operator 138
WeakPtr& operator=(const WeakPtr &rhs)139
{140
if(this!=&rhs)141
{142
destroy();143
construct(rhs);144
}145
return *this;146
}147

148
private:149
void destroy()150
{151
(*refCnt_)--;152

153
assert((*refCnt_)>=0);154
if(0==*refCnt_)155
{156
mydelete(refCnt_);157
mydelete(valid_);158
}159
160
}161
void construct(const WeakPtr &rhs)162
{163
p_ = rhs.p_;164
refCnt_ = rhs.refCnt_;165
valid_ = rhs.valid_;166
(*refCnt_)++;167
}168

169
AutoPtr *p_;170
bool *valid_;171
int *refCnt_; //weak ref cnt, always valid if one weakPtr or AutoPtr exist172
};173

174
void Test()175
{176
WeakPtr p1;177

178
assert(p1.empty());179
{180
AutoPtr p(mynew(int(100)));181
p1 = WeakPtr(p);182
assert(!p1.empty());183
assert(!p.empty());184
}185
assert(p1.empty());186

187
//mynew(int());188
}189

190
void main()191
{192
Test();193
checkMemory();194
}- 上一篇 Linux安装与启动
- 下一篇 一个数据包经过路由器和交换机各会发生什么变化.

