1.为什么引进智能指针:
他能保证在你的代码在引发异常时,不会引起内存泄漏或诸多问题
例如当你在申请一段空间后还没来得及释放,中间的代码就引发异常,导致内存泄漏
当你用fopen打开一个文件,还没fclose的时候中间的代码又引发异常。
2.什么是智能指针
(1)以指针的行为方式访问所管理的对象,需要重载指针->操作符;
(2)解引用(Dereferencing),获取所管理的对象,需要重载解引用*操作符;
(3)智能指针在其声明周期结束时自动销毁其管理的对象;
(4)引用计数、写时复制、赋值即释放对象拥有权限、控制权限转移。
几种智能指针
AutoPtr
#pragma once
#include <iostream>
#include <windows.h>
using namespace std;
struct AA
{
int a1;
int a2;
};
//模拟智能指针
template <class T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>& Ap) //浅拷贝
{
_ptr = Ap._ptr;
Ap._ptr = NULL; //管理权转移,Ap._ptr变成空指针
}
AutoPtr<T>& operator=(AutoPtr<T>& ap)
{
if (this != ap) //如果不是自己给自己赋值
{
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
}
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
~AutoPtr()
{
delete _ptr;
}
protected:
T* _ptr;
};
#include "AutoPtr.h"
void TestAutoPtr()
{
AutoPtr<AA> ap1 = new AA;
(*ap1).a1 = 10;
ap1->a1 = 20;
AutoPtr<AA> ap2(ap1);
(*ap2).a2 = 30;
ap2->a1 = 40;
AutoPtr<AA> ap3 = ap2;
}
int main()
{
TestAutoPtr();
system("pause");
return 0;
}
ScopedPtr
#pragma once
#include <iostream>
#include <windows.h>
using namespace std;
template<class T>
class ScopedPtr
{
public:
ScopedPtr(T* ptr)
:_ptr(ptr)
{}
~ScopedPtr()
{
delete _ptr;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
protected:
ScopedPtr<T>& operator=(const ScopedPtr<T>& ap); /*只声明不定义*/
ScopedPtr(const ScopedPtr<T>& ap); /*当外界想要让ScopedPtr类指针赋值或重载时就会报错*/
/*并且在protected模式下,外界不能定义*/
protected:
T* _ptr;
};
#include "ScopedPtr.h"
struct AA
{
int a1;
int a2;
};
void TestScopedPtr()
{
ScopedPtr<AA> ap1 = new AA;
(*ap1).a1 = 10;
ap1->a2 = 20;
}
int main()
{
TestScopedPtr();
system("pause");
return 0;
}
SharedPtr
#pragma once
#include <iostream>
#include <windows.h>
using namespace std;
template<class T>
class SharedPtr
{
public:
SharedPtr(T* ptr)
:_ptr(ptr)
,_refCount(new int(1)) //此时有一个指针指向这块儿被开辟的空
{}
SharedPtr(SharedPtr<T>& Sp)
:_ptr(NULL)
,_refCount(new int(0))
{
_ptr = Sp._ptr; //浅拷贝
_refCount = Sp._refCount;
++Sp._refCount[0]; //计数器加一
}
SharedPtr<T>& operator=(SharedPtr<T>& Sp)
{
if (_ptr != Sp._ptr)
{
--_refCount[0];
//判断this是否为最后一个指针
if (0 == _refCount[0]) //当前_ptr是最后一个指针,释放空间
{
delete _ptr;
delete _refCount;
}
_ptr = Sp._ptr; //浅拷贝
_refCount = Sp._refCount;
++Sp._refCount[0]; //计数器加一
}
return *this;
}
T* operator->() //'*'/'->'运算符重载,让SharedPtr类的对象能像普通指针一样使用
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
~SharedPtr()
{
if (0 == --_refCount[0]) //若_ptr维护的这段空间还有别的指针维护则不释放,else释放空间
{
delete _ptr;
delete _refCount;
_ptr = NULL;
_refCount = NULL;
}
}
protected:
T* _ptr;
int* _refCount;
};
#include "SharedPtr.h"
struct AA
{
int a1;
int a2;
};
int main()
{
SharedPtr<AA> sp1 = new AA;
(*sp1).a1 = 10;
sp1->a2 =20;
SharedPtr<AA> sp2(sp1);
SharedPtr<AA> sp3 = new AA;
(*sp3).a1 = 30;
sp3->a2 =40;
sp1 = sp3;
sp2 = sp3;
system("pause");
return 0;
}