您的位置:首页 > 编程语言 > C语言/C++

C++ auto_ptr

2015-09-02 19:43 501 查看
在C++中,auto_ptr智能管理动态分配的对象,当对象不再使用时,auto_ptr对象自动完成对被关联对象的清理工作。是C++标准库中为了解决资源泄漏问题而提供一个智能指针类模板。

auto_ptr的源代码(源自百度百科)如下:

template<class T>
class auto_ptr
{
private:
T*ap;
public:
//constructor & destructor-----------------------------------(1)
explicit auto_ptr(T*ptr=0)throw():ap(ptr)
{
}

~auto_ptr()throw()
{
delete ap;
}
//Copy & assignment--------------------------------------------(2)
auto_ptr(auto_ptr& rhs)throw():ap(rhs.release())
{
}
template<class Y>
auto_ptr(auto_ptr<Y>&rhs)throw():ap(rhs.release())
{
}
auto_ptr& operator=(auto_ptr&rhs)throw()
{
reset(rhs.release());
return*this;
}
template<class Y>
auto_ptr& operator=(auto_ptr<Y>&rhs)throw()
{
reset(rhs.release());
return*this;
}
//Dereference----------------------------------------------------(3)
T& operator*()const throw()
{
return*ap;
}
T* operator->()const throw()
{
returnap;
}
//Helper functions------------------------------------------------(4)
//value access
T* get()const throw()
{
returnap;
}
//release owner ship
T* release()throw()
{
T*tmp(ap);
ap=0;
return tmp;
}
//reset value
void reset(T*ptr=0)throw()
{
if(ap!=ptr)
{
deleteap;
ap=ptr;
}
}
//Special conversions-----------------------------------------------(5)
template<class Y>
struct auto_ptr_ref
{
Y*yp;
auto_ptr_ref(Y*rhs):yp(rhs){}
};
auto_ptr(auto_ptr_ref<T>rhs)throw():ap(rhs.yp)
{
}

auto_ptr& operator=(auto_ptr_ref<T>rhs)throw()
{
reset(rhs.yp);
return*this;
}

template<class Y>
operator auto_ptr_ref<Y>()throw()
{
returnauto_ptr_ref<Y>(release());
}

template<class Y>
operator auto_ptr<Y>()throw()
{
returnauto_ptr<Y>(release());
}
};


auto_ptr的使用说明:

1、auto_ptr在构造时获取对象的所有权,析构时释放所有权,删除所拥有的对象。所以在程序中不用关心何时释放动态分配的变量,不存在内存泄漏,提高程序的安全性。auto_ptr的使用举例如下:



2、auto_ptr析构时会删除所拥有的对象,因此,两个auto_ptr不能同时拥有同一个对象。举例如下:

int *ptr = new int(5);
cout << ptr << " "<<*ptr << endl;
auto_ptr<int> pt(ptr);
cout << pt.get() <<" "<< *pt << endl;

auto_ptr<int> pt2(ptr);
cout << pt2.get() << " " << *pt2 << endl;
return 0;
在上边的代码中,同是将整型指针ptr赋值给两个auto_ptr对象,pt和pt2,并输出地址以及地址指向的值。程序能够正常输出,但是程序在退出时将遇到问题,因为在析构pt这个对象时,编译器已经释放了ptr指向的内存单元,当编译器析构pt2时,程序将再次去释放ptr指向的内存,这是将出错。如下图所示,程序在第二次执行auto_ptr的析构函数时,报错。



3、auto_ptr定义的析构函数中使用的是delete,而不是delete[],因此,一般不使用auto_ptr对象管理指针数组。

即,一般使用下边的用法:

<span style="white-space:pre"> </span>int * array = new int[10];
auto_ptr<int> aPtr(array);
4、由于auto_ptr对裸指针完全占有,即:一个裸指针不能同时被两个以上的auto_ptr对象拥有。因此,auto_ptr的拷贝构造函数、赋值函数、辅助运算符都需要做“所有权转移”,即在拷贝或赋值时撤销被拷贝或被赋值auto_ptr对象对远指针对象的所有权。同时,同一个auto_ptr对象也不能同时拥有多个指针对象的所有权,因此,拷贝或赋值的目标对象需要先释放原来拥有的对象。
一个auto_ptr对象被赋值或者靠背后,便为null。举例如下:



再说一下裸指针,因为我最开始看到这个词的时候不知道是什么意思,然后查了一下资料,大意是:声明一个指向另一个对象的指针,那么这个指针就是一个裸指针。
然后就是在auto_ptr的代码段中,发现函数后边有跟一个throw()查了一下资料,他是函数使用者与提供者之间的一种声明,表明该函数不跑出任何异常。throw的用法如下:
1、Function() throw(errorType)//抛出指定类型的异常;
2、Function() throw()//不会抛出异常;
3、Function() throw(...),//可能是任何形式的异常。
5、auto_ptr不具有值语义,不能用到STL标准容器中。
6、auto_ptr类提供一个模版赋值函数、模版拷贝构造函数实现隐式转换,由于构造函数声明为explicit,因此,构造函数禁止隐私转换。
举例如下:

class Base
{
public:
Base();
~Base();

private:

};

class Derived:Base
{
public:
Derived();
~Derived();

private:

};
转换如下:

<span style="white-space:pre"> </span>auto_ptr<Base> apbase = auto_ptr<Derived>(new Derived);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: