-
Notifications
You must be signed in to change notification settings - Fork 0
/
countedPtr.h
319 lines (281 loc) · 8 KB
/
countedPtr.h
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#ifndef _H_INCLUDE_COUNTED_PTR
#define _H_INCLUDE_COUNTED_PTR
#include <memory>
/**
* this is a reference counting smartpointer
* do not use this for arrays, use CountedArrayPtr
*/
template <typename T>
class CountedPtr {
private:
T * ptr;
long * count;
public:
explicit CountedPtr(T * p = 0)
: ptr(p), count(new long(1)) {
}
CountedPtr(const CountedPtr<T> & p) throw()
: ptr(p.ptr), count(p.count) {
++*count;
}
~CountedPtr() throw() {
dispose();
}
CountedPtr<T>& operator= (const CountedPtr<T> & p) throw() {
if (this != &p) {
dispose();
ptr = p.ptr;
count = p.count;
++*count;
}
return *this;
}
bool isNull() const throw() {
return ptr == 0;
}
T& operator*() const throw() {
return *ptr;
}
T* operator->() const throw() {
return ptr;
}
T* get() const throw() {
return ptr;
}
private:
void dispose() {
if (--*count == 0) {
delete count;
delete ptr;
ptr = 0;
count = 0;
}
}
};
/**
* this is a reference counting smartpointer for arrays
*/
template <typename T>
class CountedArrayPtr {
private:
T * ptr;
long * count;
public:
explicit CountedArrayPtr(T * p = 0)
: ptr(p), count(new long(1)) {
}
CountedArrayPtr(const CountedArrayPtr<T> & p) throw()
: ptr(p.ptr), count(p.count) {
++*count;
}
~CountedArrayPtr() throw() {
dispose();
}
CountedArrayPtr<T>& operator= (const CountedArrayPtr<T>& p) throw() {
if (this != &p) {
dispose();
ptr = p.ptr;
count = p.count;
++*count;
}
return *this;
}
T& operator[](int index) const throw() {
return ptr[index];
}
T* get() const throw() {
return ptr;
}
private:
void dispose() {
if (--*count == 0) {
delete count;
delete [] ptr;
ptr = 0;
}
}
};
template<typename _Tp>
class auto_arr
{
private:
_Tp* _M_ptr;
public:
/// The pointed-to type.
typedef _Tp element_type;
/**
* @brief An %auto_ptr is usually constructed from a raw pointer.
* @param p A pointer (defaults to NULL).
*
* This object now @e owns the object pointed to by @a p.
*/
explicit
auto_arr(element_type* __p = 0) throw() : _M_ptr(__p) { }
/**
* @brief An %auto_ptr can be constructed from another %auto_ptr.
* @param a Another %auto_ptr of the same type.
*
* This object now @e owns the object previously owned by @a a,
* which has given up ownsership.
*/
auto_arr(auto_arr& __a) throw() : _M_ptr(__a.release()) { }
/**
* @brief An %auto_ptr can be constructed from another %auto_ptr.
* @param a Another %auto_ptr of a different but related type.
*
* A pointer-to-Tp1 must be convertible to a
* pointer-to-Tp/element_type.
*
* This object now @e owns the object previously owned by @a a,
* which has given up ownsership.
*/
template<typename _Tp1>
auto_arr(auto_arr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
/**
* @brief %auto_ptr assignment operator.
* @param a Another %auto_ptr of the same type.
*
* This object now @e owns the object previously owned by @a a,
* which has given up ownsership. The object that this one @e
* used to own and track has been deleted.
*/
auto_arr&
operator=(auto_arr& __a) throw()
{
reset(__a.release());
return *this;
}
/**
* @brief %auto_ptr assignment operator.
* @param a Another %auto_ptr of a different but related type.
*
* A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type.
*
* This object now @e owns the object previously owned by @a a,
* which has given up ownsership. The object that this one @e
* used to own and track has been deleted.
*/
template<typename _Tp1>
auto_arr&
operator=(auto_arr<_Tp1>& __a) throw()
{
reset(__a.release());
return *this;
}
/**
* When the %auto_ptr goes out of scope, the object it owns is
* deleted. If it no longer owns anything (i.e., @c get() is
* @c NULL), then this has no effect.
*
* @if maint
* The C++ standard says there is supposed to be an empty throw
* specification here, but omitting it is standard conforming. Its
* presence can be detected only if _Tp::~_Tp() throws, but this is
* prohibited. [17.4.3.6]/2
* @end maint
*/
~auto_arr() { delete [] _M_ptr; }
/**
* @brief Smart pointer dereferencing.
*
* If this %auto_ptr no longer owns anything, then this
* operation will crash. (For a smart pointer, "no longer owns
* anything" is the same as being a null pointer, and you know
* what happens when you dereference one of those...)
*/
element_type&
operator*() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return *_M_ptr;
}
/**
* @brief Smart pointer dereferencing.
*
* This returns the pointer itself, which the language then will
* automatically cause to be dereferenced.
*/
element_type*
operator->() const throw()
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return _M_ptr;
}
/**
* @brief Bypassing the smart pointer.
* @return The raw pointer being managed.
*
* You can get a copy of the pointer that this object owns, for
* situations such as passing to a function which only accepts
* a raw pointer.
*
* @note This %auto_ptr still owns the memory.
*/
element_type*
get() const throw() { return _M_ptr; }
/**
* @brief Bypassing the smart pointer.
* @return The raw pointer being managed.
*
* You can get a copy of the pointer that this object owns, for
* situations such as passing to a function which only accepts
* a raw pointer.
*
* @note This %auto_ptr no longer owns the memory. When this object
* goes out of scope, nothing will happen.
*/
element_type*
release() throw()
{
element_type* __tmp = _M_ptr;
_M_ptr = 0;
return __tmp;
}
/**
* @brief Forcibly deletes the managed object.
* @param p A pointer (defaults to NULL).
*
* This object now @e owns the object pointed to by @a p. The
* previous object has been deleted.
*/
void
reset(element_type* __p = 0) throw()
{
if (__p != _M_ptr)
{
delete [] _M_ptr;
_M_ptr = __p;
}
}
/** @{
* @brief Automatic conversions
*
* These operations convert an %auto_ptr into and from an auto_ptr_ref
* automatically as needed. This allows constructs such as
* @code
* auto_ptr<Derived> func_returning_auto_ptr(.....);
* ...
* auto_ptr<Base> ptr = func_returning_auto_ptr(.....);
* @endcode
*/
auto_arr(std::auto_ptr_ref<element_type> __ref) throw()
: _M_ptr(__ref._M_ptr) { }
auto_arr&
operator=(std::auto_ptr_ref<element_type> __ref) throw()
{
if (__ref._M_ptr != this->get())
{
delete [] _M_ptr;
_M_ptr = __ref._M_ptr;
}
return *this;
}
template<typename _Tp1>
operator std::auto_ptr_ref<_Tp1>() throw()
{ return std::auto_ptr_ref<_Tp1>(this->release()); }
template<typename _Tp1>
operator auto_arr<_Tp1>() throw()
{ return auto_arr<_Tp1>(this->release()); }
/** @} */
};
#endif