数据结构--智能指针
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构--智能指针相关的知识,希望对你有一定的参考价值。
一 智能指针的示例
A.内存泄漏
1.动态申请堆空间,用完后不归还
2.C++语言中没有垃圾回收的机制
3.指针无法控制所指堆空间的生命周期
B.当代C++软件平台中的智能指针
1.指针生命周期结束时主动释放堆空间
2.一片堆空间最多只能由一个指针标识
3.杜绝指针运算和指针比较
智能指针的设计方案
a.通过类模板描述指针的行为
能够定义不同类型的指针对象
b.重载指针特征操作符(->和*)
利用对象模拟原生指针的行为
Point类实现代码如下
#include "Object.h"
namespace MyLib
{
template <typename T>
class Pointer:public Object
{
protected:
T* m_pointer;
public:
Pointer(T* p=NULL)
{
m_pointer=p;
}
T* operator->()
{
return m_pointer;
}
const T& operator*()const
{
return *m_pointer;
}
const T* operator->()const
{
return m_pointer;
}
T& operator*()
{
return *m_pointer;
}
bool isNull()const
{
return (m_pointer==NULL);
}
T* get()const
{
return m_pointer;
}
};
}
SmartPoint的实现代码
#include "Pointer.h"
namespace MyLib
{
/*智能指针的实现(智能指针只能指向单个变量或者单个对象)
1.指针生命周期结束时主动释放空间
2.一片堆空间最多只能由一个指针标识
3.杜绝指针运算和指针比较
设计方案
1.通过类模板描述指针的行为(能够定义不同类型的指针对象)
2.重载指针特征操作符(->和*)(利用对象模拟原生指针的行为)
*/
template<typename T>//创建的指针可以指向任意的类型
class SmartPointer:public Pointer<T>//定义的类
{
public:
SmartPointer(T* p=NULL):Pointer<T>(p)
{
}
SmartPointer(const SmartPointer<T>& obj)
{
this->m_pointer=obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer=NULL;
}
SmartPointer<T>& operator =(const SmartPointer<T>& obj)
{
if(this!=obj)
{
T* p=this->m_pointer;
//delete m_pointer;
this->m_pointer=obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer=NULL;
delete p;
}
return *this;
}
~SmartPointer()
{
delete this->m_pointer;
}
};
}
在使用智能指针(SmartPointer)替换单链表(LinkList)中的原生指针会出现问题,可以发现在SmartPointer的设计方案中(一片堆空间最多只能由一个指针标识)
二.SharedPoint的实现
SharedPoint设计要点
A.类模板
通过计数机制(ref)标识堆内存
1.堆内存被指向时:ref++
2.指针被置空时:ref--
3.ref==0:释放堆内存
计数机制的原理
同时由于SharedPoint支持多个对象同时指向一片堆空间,因此,必须支持比较操作
实现的代码如下
#include "Pointer.h"
#include <cstdlib>
#include "Exception.h"
namespace MyLib
{
template<typename T>
class SharedPointer :public Pointer<T>
{
protected:
int* m_ref;
void assign(const SharedPointer<T>& obj)
{
this->m_ref=obj.m_ref;
this->m_pointer=obj.m_pointer;
if(this->m_ref)
{
(*this->m_ref)++;
}
}
public:
SharedPointer(T* p=NULL):m_ref(NULL)
{
if(p)
{
this->m_ref=static_cast<int*>(std::malloc(sizeof(int)));//在堆空间申请一个四个字节
if(this->m_ref)//内存申请成功的情况下的操作
{
*(this->m_ref)=1;
this->m_pointer=p;
}
else
{
THROW_EXCEPTION(NoEoughMemoryException,"...");
}
}
}
SharedPointer(const SharedPointer<T>& obj):Pointer<T>(NULL)
{
//都指向了堆空间
assign(obj);
}
SharedPointer<T>& operator=(const SharedPointer<T>& obj)
{
if(this!=&obj)//避免自赋值
{
clear();//在进行赋值之前 将当前的智能指针对象置空
assign(obj);
}
return *this;
}
void clear()
{
T* toDel=this->m_pointer;
int* ref=this->m_ref;
this->m_pointer=NULL;
this->m_ref=NULL;
if(ref)
{
(*ref)--;
if(*ref==0)
{
free(ref);
delete toDel;
}
}
}
~SharedPointer()
{
clear();
}
};
template <typename T>
bool operator == (const SharedPointer<T>& l,const SharedPointer<T>& r )
{
return (l.get()==r.get());
}
template <typename T>
bool operator != (const SharedPointer<T>& l,const SharedPointer<T>& r )
{
return !(l==r);
}
}
注意:
1.只能指针只能用来指向堆空间中的单个变量
2.不同类型的智能指针对象不能混合使用
3.不要使用delete释放智能指针指向的堆空间
三.小结
1.SharedPoint最大程度的模拟了原生指针的行为
2.计数机制确保多个智能指针合法的指向同一片堆空间
3.智能指针只能用于指向堆空间中的内存
4.不同类型的智能指针不要混合使用
5.堆对象的生命周期由智能指针进行管理
以上是关于数据结构--智能指针的主要内容,如果未能解决你的问题,请参考以下文章