C++ 引用计数技术及智能指针的简单实现
作者:网络转载 发布时间:[ 2015/9/25 14:06:07 ] 推荐标签:测试开发技术 .NET
智能指针类的使用与测试
至此,我们的智能指针类完成了,我们可以来看看如何使用
int main()
{
//定义一个基础对象类指针
Point *pa = new Point(10, 20);
//定义三个智能指针类对象,对象都指向基础类对象pa
//使用花括号控制三个指针指针的生命期,观察计数的变化
{
SmartPtr sptr1(pa);//此时计数count=1
{
SmartPtr sptr2(sptr1); //调用复制构造函数,此时计数为count=2
{
SmartPtr sptr3=sptr1; //调用赋值操作符,此时计数为conut=3
}
//此时count=2
}
//此时count=1;
}
//此时count=0;pa对象被delete掉
cout << pa->getX ()<< endl;
system("pause");
return 0;
}
来看看运行结果咯:
还有2个指针指向基础对象
还有1个指针指向基础对象
-17891602
请按任意键继续. . .
如期,在离开大括号后,共享基础对象的指针从3->2->1->0变换,后计数为0时,pa对象被delete,此时使用getX()已经获取不到原来的值。
智能指针类的改进一
虽然我们的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;
if (--rp->count == 0)
delete rp;
rp = rhs.rp;
return *this;
}
~SmartPtr() {
if (--rp->count == 0)
delete rp;
else
cout << "还有" << rp->count << "个指针指向基础对象" << endl;
}
Point & operator *() //重载*操作符
{
return *(rp->p);
}
Point* operator ->() //重载->操作符
{
return rp->p;
}
private:
RefPtr *rp;
};
然后我们可以像指针般使用智能指针类
Point *pa = new Point(10, 20);
SmartPtr sptr1(pa);
//像指针般使用
cout<<sptr1->getX();
智能指针改进二
目前这个智能指针智能用于管理Point类的基础对象,如果此时定义了个矩阵的基础对象类,那不是还得重新写一个属于矩阵类的智能指针类吗?但是矩阵类的智能指针类设计思想和Point类一样啊,不能借用吗?答案当然是能,那是使用模板技术。为了使我们的智能指针适用于更多的基础对象类,我们有必要把智能指针类通过模板来实现。这里贴上上面的智能指针类的模板版:
//模板类作为友元时要先有声明
template <typename T>
class SmartPtr;
template <typename T>
class U_Ptr //辅助类
{
private:
//该类成员访问权限全部为private,因为不想让用户直接使用该类
friend class SmartPtr<T>; //定义智能指针类为友元,因为智能指针类需要直接操纵辅助类
//构造函数的参数为基础对象的指针
U_Ptr(T *ptr) :p(ptr), count(1) { }
//析构函数
~U_Ptr() { delete p; }
//引用计数
int count;
//基础对象指针
T *p;
};
template <typename T>
class SmartPtr //智能指针类
{
public:
SmartPtr(T *ptr) :rp(new U_Ptr<T>(ptr)) { } //构造函数
SmartPtr(const SmartPtr<T> &sp) :rp(sp.rp) { ++rp->count; } //复制构造函数
SmartPtr& operator=(const SmartPtr<T>& rhs) { //重载赋值操作符
++rhs.rp->count; //首先将右操作数引用计数加1,
if (--rp->count == 0) //然后将引用计数减1,可以应对自赋值
delete rp;
rp = rhs.rp;
return *this;
}
T & operator *() //重载*操作符
{
return *(rp->p);
}
T* operator ->() //重载->操作符
{
return rp->p;
}
~SmartPtr() { //析构函数
if (--rp->count == 0) //当引用计数减为0时,删除辅助类对象指针,从而删除基础对象
delete rp;
else
cout << "还有" << rp->count << "个指针指向基础对象" << endl;
}
private:
U_Ptr<T> *rp; //辅助类对象指针
};
好啦,现在我们能够使用这个智能指针类对象来共享其他类型的基础对象啦,比如int:
int main()
{
int *i = new int(2);
{
SmartPtr<int> ptr1(i);
{
SmartPtr<int> ptr2(ptr1);
{
SmartPtr<int> ptr3 = ptr2;
cout << *ptr1 << endl;
*ptr1 = 20;
cout << *ptr2 << endl;
}
}
}
system("pause");
return 0;
}
运行结果如期所愿,SmartPtr类管理起int类型来了:
2
20
还有2个指针指向基础对象
还有1个指针指向基础对象
请按任意键继续. . .
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南