智能指针:
在C++中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。使用普通指针,容易造成堆内存泄露,二次释放等问题,使用智能指针能更好的管理堆内存。C++11中引入了智能指针的概念,方便管理堆内存。
栈、堆区别
栈:系统开辟 系统释放
堆:手动开辟 手动释放
设计:手动开辟 系统释放
图示:
手动开辟堆内存,利用对象生存周期结束后会调用析构,让对象来管理这个堆内存,从而达到 手动开辟,系统析构的目的。
最初始的智能指针:管理权唯一
如果有多个智能指针指向同一个堆内存,会在拷贝构造或赋值过程中让其他的智能指针失效(置空)
#include<iostream>
using namespace std;
template<typename T>
class SmartPtr
{
public:
SmartPtr(T* ptr=NULL):mptr(ptr){}
SmartPtr(const SmartPtr& rhs):mptr(rhs.mptr)//让两个智能指针指向同一个堆内存
{
rhs.Release();
}
SmartPtr<T> operator=(const SmartPtr<T>& rhs)
{
if (this != &rhs)
{
delete mptr;//要么有唯一智能指针指向堆内存,要么指向空
mptr = rhs.mptr;
rhs.Release();
}
return *this;
}
~SmartPtr()
{
delete mptr;
mptr = NULL;
}
private:
void Release()const//旧的智能指针置为空
{
(T*)mptr = NULL;
}
private:
T* mptr;
};
int main()
{
int *p=new int;//堆内存
SmartPtr<int> sp1(p);
SmartPtr<int> sp2(sp1);
sp1=sp2;
return 0;
}
调试结果:
可以看出,当生成sp2时,sp1指向为空,指向的内存正是p所指向的堆内存。
可以看出,sp1=sp2;执行后,内存的管理权在sp1手上。
普通指针有指向和解引用的使用方法,同理智能指针也具有,需要运算符的重载。
#include<iostream>
using namespace std;
template<typename T>
class SmartPtr
{
public:
SmartPtr(T* ptr = NULL) :mptr(ptr) {}
SmartPtr(const SmartPtr& rhs) :mptr(rhs.mptr)//让两个智能指针指向同一个堆内存
{
rhs.Release();
}
SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
{
if (this != &rhs)
{
delete mptr;//要么有唯一智能指针指向堆内存,要么指向空
mptr = rhs.mptr;
rhs.Release();
}
return *this;
}
T& operator*()//解引用运算符的重载
{
return *mptr;
}
T* operator->()//指向运算符的重载
{
return mptr;
}
~SmartPtr()
{
delete mptr;
mptr = NULL;
}
private:
void Release()const//旧的智能指针置为空
{
(T*)mptr = NULL;
}
private:
T* mptr;
};
class Test
{
public:
Test(int a):ma(a){}
void Show()
{
cout << ma << endl;
}
private:
int ma;
};
int main()
{
int *p=new int;//堆内存
SmartPtr<int> sp1(p);
SmartPtr<int> sp2(sp1);
sp1 = sp2;
//普通指针的用法
Test *ptest = new Test(30);//成员变量是 Test *mptr;
ptest->Show();
//智能指针的用法
SmartPtr<Test> sp3(ptest);
sp3->Show();
(*sp3.operator->()).Show();
return 0;
}
解释:(*sp3.operator->()).Show();//(sp3.operator->())->Show();
sp3.operator->()返回一个 T* 指针,*T解引用,即对象,对象调用方法,合情合理。