智能指针RAII:资源分配及初始化,定义一个类来封装资源的分配和初始化,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放
#pragma
once
//AutoPtr 智能指针
template
<
class
T
>
class
AutoPtr
{
public
:
//构造函数
AutoPtr(
T
*
ptr
)
:_ptr(
ptr
)
{}
//拷贝构造
//把ap1股给ap2后,再把自己置为空,不再管理这个内存空间
AutoPtr(
AutoPtr
<
T
>&
ap
)
:_ptr(
ap
._ptr)
{
ap
._ptr =
NULL
;
}
//赋值运算符重载
//释放ap3,让ap3指向ap2所指空间,再把ap2置空
AutoPtr
<
T
>& operator=(
AutoPtr
<
T
>&
ap
)
{
if
(
this
!= &
ap
)
{
cout <<
"delete:"
<< _ptr << endl;
delete
_ptr;
_ptr =
ap
._ptr;
ap
._ptr =
NULL
;
}
return
*
this
;
}
//析勾函数
~AutoPtr()
{
if
(_ptr)
{
cout <<
"delete:"
<< _ptr << endl;
delete
_ptr;
_ptr =
NULL
;
}
}
//operator*
T
& operator*()
{
return
*_ptr;
}
//operator->
T
* operator->()
{
return
_ptr;
}
//getPtr
T
* GetPtr()
{
return
_ptr;
}
protected
:
T
* _ptr;
};
// 智能指针管理一块内存的释放
// 智能指针是一个类,有类似指针的功能
struct
Node
{
int
_data;
Node
* _next;
};
void
TestAutoPtr()
{
int
* p1 =
new
int
(2);
int
* p2 = p1;
int
* p3;
p3 = p2;
*p1 = 10;
//会造成两次析勾,类似于浅拷贝,ap1,ap2都指向同一块内存空间,第一个析勾后,
//第二个就成为野指针
AutoPtr
<
int
> ap1(
new
int
(1));
AutoPtr
<
int
> ap2 = ap1;
//AutoPtr ap2(ap1);
//释放ap3,让ap3指向ap2所指空间,再把ap2置空
AutoPtr
<
int
> ap3(
new
int
(3));
ap3 = ap2;
*ap3 = 10;
//*ap1 = 30;
AutoPtr
<
Node
> apNode(
new
Node
);
apNode->_data = 10;
delete
p1;
}
//AutoPtr容易出错,因为前面的指针已经置为空,存在潜在危险,没有完全达到指针的效果,
//ScopedPtr 智能指针
template
<
class
T
>
class
ScopedPtr
{
public
:
//构造函数
ScopedPtr(
T
*
ptr
)
:_ptr(
ptr
)
{}
//析勾函数
~ScopedPtr()
{
if
(_ptr)
{
cout <<
"delete:"
<< _ptr << endl;
delete
_ptr;
}
}
//重载*
T
& operator*()
{
return
*_ptr;
}
//operator->
T
* operator->()
{
return
_ptr;
}
//GetPtr
T
* GetPtr()
{
return
_ptr;
}
protected
:
//1.限定符为protected,不能进行拷贝,2.将拷贝构造和赋值运算符的重载声明出来
//不能让他调用默认的,也不能在外面定义它
ScopedPtr(
const
ScopedPtr
<
T
>& sp);
ScopedPtr
<
T
> operator=(
const
ScopedPtr
<
T
>& sp);
protected
:
T
* _ptr;
};
//防止别人在类外面定义它
//template<class T>
//ScopedPtr<T>::ScopedPtr(const ScopedPtr<T>& sp)
// :_ptr(sp._ptr)
//{}
void
TestScopedPtr()
{
ScopedPtr
<
int
> sp1(
new
int
(1));
//ScopedPtr<int> sp2(sp1);
}
//SharedPtr 利用引用计数来解决这个问题
template
<
class
T
>
class
SharedPtr
{
public
:
SharedPtr(
T
*
ptr
)
:_ptr(
ptr
)
, _pCount(
new
long
(1))
{}
~SharedPtr()
{
_Release();
}
//只是改变pcount
SharedPtr(
const
SharedPtr
<
T
>&
sp
)
:_ptr(
sp
._ptr)
, _pCount(
sp
._pCount)
{
++(*_pCount);
}
赋值运算符的传统写法
//SharedPtr<T>& operator=(const SharedPtr<T>& sp)
//{
// if (this != &sp)
// {
// this->_Release();
// _pCount = sp._pCount;
// _ptr = sp._ptr;
// ++(*_pCount);
// }
// return *this;
//}
//现代写法
SharedPtr
<
T
>& operator=(
SharedPtr
<
T
>
sp
)
{
swap(_ptr,
sp
._ptr);
swap(_pCount,
sp
._pCount);
return
*
this
;
}
T
& operator*()
{
return
*_ptr;
}
T
* operator->()
{
return
_ptr;
}
T
* GetPtr()
{
return
_ptr;
}
long
GetCount()
{
return
*_pCount;
}
protected
:
void
_Release()
{
//如果指向这个的引用计数为0才delete,其他时候只是前置减减
if
(--(*_pCount) == 0)
{
delete
_ptr;
delete
_pCount;
}
}
protected
:
T
* _ptr;
long
* _pCount;
};
void
TestSharedPtr()
{
SharedPtr
<
int
> sp1(
new
int
(1));
SharedPtr
<
int
> sp2(sp1);
cout << sp1.GetCount() << endl;
SharedPtr
<
int
> sp3(
new
int
(2));
sp3 = sp1;
}