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());
}
};
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);
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);
相关文章推荐
- C++primer 阅读笔记-模板与泛型编程(成员模板)
- C++项目开发常用的开源库
- C++模板元编程 - 1 基本数据类型和运算
- 协变(Covariance)与逆变(Contravariance)
- 从 C/C++ 程序调用 Java 代码
- 漫谈C指针第三讲---指针是什么东西
- 一些不常见的C++关键字
- Python调用C++程序备忘笔记
- [C++][编程风格]C++命名规则
- Android-使用C++实现调用本地方法返回字符串显示在界面上/NDK-JNI开发实例(八)
- 带重复元素的排列
- C++简单封装互斥量
- C++编译器如何对Const常量进行分配存储空间
- c++命名空间
- 漫谈C指针第二讲---变量赋值与取地址
- 初识泛型
- 【C++】双向链表
- C++primer 阅读笔记-模板与泛型编程(模板参数)
- 【C++】String_COW(写时拷贝)
- C/C++