[C/C++] Very very good !!! 句柄类
方案二
为了避免上面方案中每个使用指针的类自己去控制引用计数,可以用一个类把指针封装起来。封装好后,这个类对象可以出现在用户类使用指针的任何地方,表现为一个指针的行为。我们可以像指针一样使用它,而不用担心普通成员指针所带来的问题,我们把这样的类叫句柄类。在封装句柄类时,需要申请一个动态分配的引用计数空间,指针与引用计数分开存储。实现示例如下:
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <stack> #include <deque> #include <queue> #include <bitset> #include <list> #include <map> #include <set> #include <iterator> #include <algorithm> #include <functional> #include <utility> #include <sstream> #include <climits> #include <cassert> #include <stdexcept> #define BUG puts("here!!!"); using namespace std; class Stub { public : void show() { printf("Stub showed!"); } ~Stub() { cout << "Stub : Destructor" << endl; } }; template <typename T> class Handle { public : Handle(T *p = 0) : ptr(p), pUse(new size_t(1)) {} Handle(const T& src) : ptr(src.ptr), pUse(src.pUse) { *pUse++; } Handle& operator= (const Handle &rhs) { ++*rhs.pUse; decrUse(); ptr = rhs.ptr; pUse = rhs.pUse; return *this; } T *operator-> () { if(ptr) return ptr; throw std::runtime_error("NULL point"); } const T *operator-> () const { if(ptr) return ptr; throw std::runtime_error("NULL point"); } T &operator* () { if(ptr) return *ptr; throw std::runtime_error("NULL point"); } const T &operator* () const { if(ptr) return *ptr; throw std::runtime_error("NULL point"); } ~Handle() { decrUse(); std::cout << "Handle destructor" << endl; } private : void decrUse() { --(*pUse); // if(*pUse == 0) { delete ptr; delete pUse; } } T *ptr; size_t *pUse; }; int main() { try { Handle<Stub> t; t->show(); } catch (const exception& err) { cout << err.what() << endl; } BUG Handle<Stub> t1(new Stub); Handle<Stub> t2(t1); (*t2).show(); return 0; }