什么是智能指针?
智能指针实质上是一个类,定义一个类来封装资源的分配和释放。这个类的构造函数中传入一个指针,完成资源的分配和初始化。在析构函数中释放传入的该指针,完成资源的释放。
为什么要用智能指针?
智能指针就是智能,自动化的管理指针所指向的动态资源。
例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露。
// case1
void Test2()
{
int* p1 = new int(2);
bool isEnd = true;
//...
if (isEnd)
{
delete p1;
return;
}
//...
delete p1;
}
// case2
void DoSomeThing()
{
//...
throw 2;
//...
}
void Test2()
{
int* p1 = new int(2);
//...
try {
DoSomeThing();
}
catch (...)
{
delete p1;
throw;
}
//...
delete p1;
}
智能指针的简单实现。
Auto_ptr:不能共享所有权,只要出现两个指针指向同一块资源,就释放前一个指针的管理权。保证只有一个指针指向一块资源。
Scoped_ptr:将类中的成员函数拷贝构造和赋值运算符只申明为protected,不定义。所以不可能有两个指针指向同一个对象。
Shared_ptr:采用引用计数的方法。将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针。
ScopedArray和Scoped_ptr类似,只是操作的是数组。SharedArray同理。
template <class T>
class AutoPtr
{
public:
AutoPtr(T*ptr)
:_ptr(ptr)
{}
AutoPtr( AutoPtr<T>&ap)
:_ptr(ap._ptr)
{
ap._ptr = NULL;
}
AutoPtr<T>&operator=(const AutoPtr<T>&ap)
{
if (this != &ap)
{
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
}
}
~AutoPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
T*GetPtr()
{
return _ptr;
}
protected:
T*_ptr;
};
struct Node
{
int _data;
Node*_next;
};
void Test_AutoPtr()
{
int*p1 = new int(2);
int*p2 = p1;
int*p3 = p2;
*p3 = 10;
delete p1;
AutoPtr<int>ap1(new int(2));
AutoPtr<int>ap2=ap1; //此时ap1为NULL,无管理权
AutoPtr<int>ap3(ap2);
//此时ap2为NULL,无管理权
//*ap2 = 10; //程序崩溃
*ap3 = 10;
AutoPtr<Node>sp1(new Node);
sp1->_data = 10;
}
template<class T>
class ScopedPtr
{
public:
ScopedPtr(T*ptr)
:_ptr(ptr)
{}
~ScopedPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
T*GetPtr()
{
return _ptr;
}
protected: //只申明,不定义,防止拷贝构造和赋值运算符重载。
ScopedPtr(const ScopedPtr<T>&sp); //保护,防止在外定义。若写为public,则有可能在类外定义。
ScopedPtr<T>& operator=(const ScopedPtr<T>&sp);
protected:
T*_ptr;
};
void Test_ScopedPtr()
{
ScopedPtr<int>sp1(new int(3));
//ScopedPtr<int>sp2(sp1); //protectd:无法访问
}
template <class T>
class ScopedArray
{
public:
ScopedArray(T*ptr)
:_ptr(ptr)
{}
~ScopedArray()
{
if (_ptr)
{
delete[]_ptr;
}
}
T&operator[](size_t Index)
{
return _ptr[Index];
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
T*GetPtr()
{
return _ptr;
}
protected:
ScopedArray(const ScopedArray<T>&sp);
ScopedArray<T>&operator=(const ScopedArray<T>&sp);
protected:
T*_ptr;
};
void Test_ScopedArray()
{
ScopedArray<int>sp1(new int[5]);
//ScopedPtr<int>sp2(sp1);
}
template <class T>
class SharedPtr
{
public:
SharedPtr(T*ptr)
:_ptr(ptr)
, _Pcount(new long(1))
{}
SharedPtr(const SharedPtr<T>&sp)
:_ptr(sp._ptr)
, _Pcount(sp._Pcount)
{
++*(_Pcount);
}
//SharedPtr<T>&operator=(const SharedPtr<T>&sp) //传统写法
//{
// if (this != &sp)
// {
// if (--(*_Pcount) == 0)
// {
// delete _ptr;
// delete _Pcount;
// }
// _ptr = sp._ptr;
// _Pcount = sp._Pcount;
// ++(*_Pcount);
// }
// return *this;
//}
SharedPtr<T>&operator=(const SharedPtr<T>sp) //现代写法
{
swap(_ptr, sp._ptr);
swap(_Pcount, sp._Pcount);
return *this;
}
~SharedPtr()
{
if (--(*_Pcount) == 0)
{
delete _ptr;
delete _Pcount;
}
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
T*GetPtr()
{
return _ptr;
}
long GetCount()
{
return *_Pcount;
}
protected:
T*_ptr;
long*_Pcount;
};
void Test_SharedPtr()
{
SharedPtr<int>sp1(new int(2));
SharedPtr<int>sp2(sp1);
}
template <class T>
class SharedArray
{
public:
SharedArray(T*ptr)
:_ptr(ptr)
, _Pcount(new long (1))
{}
SharedArray(const SharedArray<T>&sp)
:_ptr(sp._ptr)
, _Pcount(sp._Pcount)
{
++*(_Pcount);
}
SharedArray<T>&operator=(const SharedArray<T>sp) //现代写法
{
swap(_ptr, sp._ptr);
swap(_Pcount, sp._Pcount);
return *this;
}
~SharedArray()
{
if (--(*_Pcount) == 0)
{
delete[] _ptr;
delete _Pcount;
}
}
T&operator*()
{
return *_ptr;
}
T*operator->()
{
return _ptr;
}
T*GetPtr()
{
return _ptr;
}
T&operator[](size_t Index)
{
return _ptr[Index];
}
long GetCount()
{
return *_Pcount;
}
protected:
T*_ptr;
long*_Pcount;
};
void Test_SharedArray()
{
SharedArray<int>sp1(new int[5]);
SharedArray<int>sp2(sp1);
}
转载于:https://blog.51cto.com/10741125/1782624