C++ 智能指针深入解析
1. 为什么需要智能指针? 2. 智能指针的实现概述 3. 实现方式1:引入辅助类 复制代码 代码如下: class Point //基础对象类 { public: Point(int xVal = 0,int yVal = 0):x(xVal),y(yVal) { } int getX() const { return x; } int getY() const { return y; } void setX(int xVal) { x = xVal; } void setY(int yVal) { y = yVal; } private: int x,y; }; class RefPtr //辅助类 { //该类成员访问权限全部为private,因为不想让用户直接使用该类 friend class SmartPtr; //定义智能指针类为友元,因为智能指针类需要直接操纵辅助类 RefPtr(Point *ptr):p(ptr),count(1) { } ~RefPtr() { delete p; } int count; //引用计数 Point *p; //基础对象指针 }; class SmartPtr //智能指针类 { public: SmartPtr(Point *ptr):rp(new RefPtr(ptr)) { } //构造函数 SmartPtr(const SmartPtr &sp):rp(sp.rp) { ++rp->count; } //复制构造函数 SmartPtr& operator=(const SmartPtr& rhs) { //重载赋值操作符 ++rhs.rp->count; //首先将右操作数引用计数加1, if(--rp->count == 0) //然后将引用计数减1,可以应对自赋值 delete rp; rp = rhs.rp; return *this; } ~SmartPtr() { //析构函数 if(--rp->count == 0) //当引用计数减为0时,删除辅助类对象指针,从而删除基础对象 delete rp; } private: RefPtr *rp; //辅助类对象指针 }; int main() { Point *p1 = new Point(10,8); SmartPtr sp1(p1); SmartPtr sp2(sp1); Point *p2 = new Point(5,5); SmartPtr sp3(p2); sp3 = sp1; return 0; } 使用该方式的内存结构图如下: 为了避免上面方案中每个使用指针的类自己去控制引用计数,可以用一个类把指针封装起来。封装好后,这个类对象可以出现在用户类使用指针的任何地方,表现为一个指针的行为。我们可以像指针一样使用它,而不用担心普通成员指针所带来的问题,我们把这样的类叫句柄类。在封装句柄类时,需要申请一个动态分配的引用计数空间,指针与引用计数分开存储。实现示例如下: 复制代码 代码如下: class Point //基础对象类 { public: Point(int xVal = 0,y(yVal) { } int getX() const { return x; } int getY() const { return y; } void setX(int xVal) { x = xVal; } void setY(int yVal) { y = yVal; } public: virtual Point* clone() const { //虚函数,为了实现让句柄类在不知道对象的确切类型的情况下分配已知对象的新副本 return new Point(*this); } private: int x,y; }; class D3Point : public Point //派生类 { public: D3Point(int xVal,int yVal,int zVal):Point(xVal,yVal),z(zVal) { } int getZ() const { return z; } void setZ(int zVal) { z = zVal; } public: D3Point* clone() const { //虚函数,为了实现让句柄类在不知道对象的确切类型的情况下分配已知对象的新副本 return new D3Point(*this); } private: int z; }; class SmartPtr { public: SmartPtr(Point *ptr = 0):p(ptr),count(new int(1)) { } //构造函数 SmartPtr(Point &point):p(point.clone()),count(new int(1)) { } //构造函数 SmartPtr(const SmartPtr &sp):p(sp.p),count(sp.count) { ++*count; } //复制构造函数 SmartPtr& operator=(const SmartPtr &sp) { //重载赋值操作符 ++*sp.count; //首先将右操作数引用计数加1, decr_use(); //然后将引用计数减1,可以应对自赋值 p = sp.p; count = sp.count; return *this; } ~SmartPtr() { //析构函数 decr_use(); } public: //一般情况下不会实现这两个操作符,因为我们不希望用户直接操纵基础对象指针 const Point* operator->() const { if(p) return p; else throw logic_error("Unbound Point"); } const Point& operator*() const { if(p) return *p; else throw logic_error("Unbound Point"); } private: void decr_use() { if(--*count == 0) { delete p; delete count; } } private: Point *p; //基础对象指针 int *count; //指向引用计数的指针 }; int main() { Point *p1 = new Point(10,8); SmartPtr sp1(p1); SmartPtr sp2(sp1); D3Point *p2 = new D3Point(5,5,0); SmartPtr sp3(p2); return 0; } 使用该方式的内存结构图如下: 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |