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
| #include <algorithm>
/* * shared_ptr_count is a container for the allocated pn reference counter. */ class shared_ptr_count { public: shared_ptr_count() : pn(nullptr) {} shared_ptr_count(const shared_ptr_count& count) : pn(count.pn) {} // swap method for the copy-and-swap idiom (copy constructor and swap method) void swap(shared_ptr_count& lhs) throw() { std::swap(pn, lhs.pn); } // getter of the underlying reference counter long use_count() const throw() { long count(0); if (nullptr != pn) { count = *pn; } return count; } // acquire/share the ownership of the pointer, initializing the reference counter template <class U> void acquire(U* p) { if (nullptr != p) { if (nullptr == pn) { try { pn = new long(1); // may throw std::bad_alloc } catch (std::bad_alloc&) { delete p; throw; // rethrow the std::bad_alloc } } else { ++(*pn); } } } // release the ownership of the px pointer, destroying the object when appropriate template <class U> void release(U* p) { if (nullptr != pn) { --(*pn); if (0 == *pn) { delete p; delete pn; } pn = nullptr; } } public: long* pn; // Reference counter }; /* * shared_ptr is a smart pointer retaining ownership of an object throught a provided pointer, * and sharing this ownership with a reference counter. * It destroys the object when the last shared pointing to it is destroyed or reset. */ template<typename T> class shared_ptr { public: // The type of the managed object, aliased as member type typedef T element_type; // Default constructor shared_ptr(void) throw() : px(nullptr), pn() {} // Constructor with the provided pointer to manage explicit shared_ptr(T* p) : pn() { acquire(p); } // Copy constructor (used by the copy-and-swap idiom) shared_ptr(const shared_ptr& ptr) throw() : pn(ptr.pn) { acquire(ptr.px); } // Assignment operator using the copy-and-swap idiom (copy constructor and swap method) shared_ptr& operator=(shared_ptr ptr) throw() { swap(ptr); return *this; } // Destructor releases its ownership inline ~shared_ptr() throw() { release(); } // Reset releases its ownership inline void reset() throw() { release(); } // Reset release its ownership and re-acquire another one void reset(T* p) { release(); acquire(p); } // Swap method for the copy-and-swap idiom void swap(shared_ptr& lhs) throw() { std::swap(px, lhs.px); pn.swap(lhs.pn); } // reference counter operations: inline operator bool() const throw() { return (0 < pn.use_count()); } inline bool unique() const throw() { return (1 == pn.use_count()); } long use_count() const throw() { return pn.use_count(); } // Underlying pointer operations: inline T& operator*() const throw() { return *px; } inline T* operator->() const throw() { return px; } inline T* get() const throw() { return px; }
private: // acquire/share the ownership of the px pointer, initializing the reference counter inline void acquire(T* p) { pn.acquire(p); // may throw std::bad_alloc px = p; // here it is safe to acquire the ownership of the provided raw pointer, where exception cannot be thrown any more } // release the ownership of the px pointer, destroying the object when appropriate inline void release() throw() { pn.release(px); px = nullptr; } private: T* px; // Native pointer shared_ptr_count pn; // Reference counter };
// comparasion operators template<class T, class U> inline bool operator==(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() == r.get()); } template<class T, class U> inline bool operator!=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() != r.get()); } template<class T, class U> inline bool operator<=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() <= r.get()); } template<class T, class U> inline bool operator<(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() < r.get()); } template<class T, class U> inline bool operator>=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() >= r.get()); } template<class T, class U> inline bool operator>(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws { return (l.get() > r.get()); }
|