智能指针提出的原因及解决办法:
在C++中主要使用new和delete来分配和释放内存,内存的释放是由程序员来操作,但由于我们常常忘记释放内存导致内存泄漏问题。于是在C++11中提出了智能指针的概念,以便于管理内存。
通常在new一个新的对象时会在堆上申请一块内存,在进行复制或赋值操作时会导致多个指针指向同一块内存,如果其中一个指针进行操作,如果删除该指针指向的对象,会导致其他指针指向的对象也都不存在了,这些指针就成可悬垂指针。还有如果忘记释放会导致内存的泄漏,而使用智能指针的原因就是为了合理的管理着块内存,避免内存泄漏和悬垂指针的出现。
智能指针的实现核心就是通过一个类管理被new出来的对象,具体是靠引用计数来实现(还有句柄类)。
主要有四种智能指针:auto_ptr,以及在C++11版本之后提出的三种智能指针:shared_ptr,unique_ptr,weak_ptr; 包含在头文件<memory>中;
auto_ptr
auto_ptr的实现原理为RAII(资源获取即初始化);主要是为了解决"有异常抛出时发生内存泄漏"的问题。
auto_ptr对象通过初始化指向有new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时。其析构函数会将auto_ptr拥有的动态内存自动释放。即使发生异常,通过异常的栈展开过程也能将动态内存释放。auto_ptr不支持new数组。
使用方法:
auto_ptr<type> ptr(new type());//该指针的定义形式,其中type是指针指向的类型,ptr是该指针的名称。
//也可以先定义,后赋值,如下所示:
auto_ptr<map<int,int>> ptr;
ptr=auto_ptr<map<int,int>> (new map<int,vector<int>>());
我们知道可以用多个指针指向同一块内存,但是一块内存的管理权限只能一个拥有,当其中一个指针释放内存后,其他指针就会指向非法内存。所以我们需要将权限设置为两部分,一是管理权二是释放权,只要保证释放权唯一就不会出现悬垂指针;
具体代码实现:
#include<iostream>
using namespace std;
template<typename T>
class auto_Ptr{
public:
auto_Ptr(T* ptr):mptr(ptr),flag(true){}//构造函数
auto_Ptr(const auto_Ptr<T>& rhs) :mptr(rhs.mptr)//拷贝构造函数
{
flag=rhs.flag;
rhs.flag=false;
}
auto_Ptr<T>& operator=(const auto_Ptr<T>& rhs)//赋值运算符的重载函数
{
if(this!=&rhs)
{
this->~auto_Ptr();
mptr=rhs.mptr;
rhs.Release();
rhs.flag=false;
}
return *this;
}
T& operator*()
{
return *mptr;
}
T* operator->()
{
return mptr;
}
~auto_Ptr()
{
if(flag)
{
delete mptr;
}
mptr=NULL;
}
private:
T *mptr;
mutable bool flag;//标记释放权所属
};
void Test(auto_Ptr<int> sp)
{
}
int main()
{
auto_Ptr<int> sp1(new int);//sp1指向开辟的内存块,sp1拥有释放权
auto_Ptr<int> sp2(sp1);//利用sp1靠内构造生成sp2,sp1释放权转移到sp2
*sp1=10;
return 0;
}