以对象管理资源——C++智能指针auto_ptr简介
auto_ptr是C++标准库提供的类模板,它可以帮助程序员自动管理用new表达式动态分配的单个对象。auto_ptr对象被初始化为指向由new表达式创建的对象,当auto_ptr对象的生命期结束时,动态分配的对象会被自动释放。auto_ptr为动态分配内存提供了大量的便利和安全性。通过使用auto_ptr,程序员不再需要关心new出来的对象何时delete,而且在子程序异常跳出时仍能保证动态分配的对象正常析构。
在使用auto_ptr之前,必须包含以下的头文件:
#include<memory>
auto_ptr对象的定义有三种形式:
(1)auto_ptr< type_pointed_to > identifier( ptr_allocated_by_new);
(2)auto_ptr< type_pointed_to > identifier( auto_ptr_of_same_type);
(3)auto_ptr< type_pointed_to > identifier;
其中,type_pointed_to表示由new表达式创建的对象的类型。例如,auto_ptr第一种的使用形式:
auto_ptr< int> pi( new int( 1024 ) );
pi被初始化为由new表达式创建的对象的地址(该int对象的初始值为1024)。然后,我们可以像使用普通指针一样使用pi,如:
if ( *pi != 1024)
; // 出错了
else
*pi *= 2;
new表达式创建的对象(即资源对象)由pi指向,当pi对生命期结束时,资源对象将被自动释放。这种“以对象(pi)管理资源(new创建的int对象)”的观念常被称为“资源取得时机便是初始化时机”(Resource Acquisition Is Initialization; RAII)。同时我们看到,new表达式创建的对象的释放是通过pi生命期结束时调用pi的析构函数实现,这实际上也说明了一种管理资源的观念,即“资源管理对象(managing object)运用析构函数确保资源被释放”。不论程序的控制流如何流转,只要managing object离开作用域,资源都会被释放。
假如我们希望以一个class类型的对象初始化auto_ptr对象,例如标准string类型,会是怎么样呢?如:
auto_ptr< string > pstr_auto( new string( “an auto release string” ) );
使用pstr_auto的使用就像使用普通的string*指针,如:
if (pstr_auto->empty() )
; // 字符串为空的处理
auto_ptr背后的动机是支持与普通指针类型相同的语法,但是为auto_ptr对象所指对象的释放提供自动管理。根据一般常识,你可能会认为这种额外的便利和安全性会带来一定的开销,但实际情况并不这样。因为对这些操作的支持都是内联的,所以auto_ptr对象并不比直接使用指针代价更高。
了解了auto_ptr的使用方法,我们再看下其声明。以下的auto_ptr的声明摘自ISO/IEC 14882, section 20.4.5:
namespace std {
template <class Y> struct auto_ptr_ref {};
template <class X>
class auto_ptr {
public:
typedef X element_type;
// 20.4.5.1 construct/copy/destroy:
explicit auto_ptr(X* p =0) throw();
auto_ptr(auto_ptr&) throw();
template <class Y> auto_ptr(auto_ptr<Y>&) throw();
auto_ptr& operator=(auto_ptr&) throw();
template <class Y> auto_ptr& operator=(auto_ptr<Y>&) throw();
auto_ptr& operator=(auto_ptr_ref<X>) throw();
~auto_ptr() throw();
// 20.4.5.2 members:
X& operator*() const throw();
X* operator->() const throw();
X* get() const throw();
X* release() throw();
void reset(X* p =0) throw();
// 20.4.5.3 conversions:
auto_ptr(auto_ptr_ref<X>) throw();
template <class Y> operator auto_ptr_ref<Y>() throw();
template <class Y> operator auto_ptr<Y>() throw();
};
}
可以看到,auto_ptr是一类模板,它提供了几种初始化方法和提供了对赋值运算以及常见指针运算符号的重载。正是这些运算符的重载,使得我们使用auto_ptr就像使用普通指针一样。
在使用auto_ptr时,须十分注意资源所有权的概念。例如,对于上面定义的pstr_auto,string对象的所有者毫无疑问是pstr_auto对象,
auto_ptr< string > pstr_auto( new string( “an auto release string” ) );
然后使用pstr_auto来初始化pstr_auto2,
auto_ptr<string> pstr_auto2( pstr_auto);
这时,new创建对string对象的所有者会发生怎样的变化呢?我们当然不希望让两个auto_ptr对象都拥有同一个资源对象的所有权——这会引起重复删除对象的问题,这也是auto_ptr需要防止的。
当一个auto_ptr对象被另一个auto_ptr对象初始化或赋值时,左边被赋值或初始化的对象就拥有了资源对象的所有权,而右边的auto_ptr对象则撒消所有权。在上面string对象例子中,pstr_auto2获取所有权,而pstr_auto则不再拥有所有权。
类似的所有权变化也发生在赋值运算上面。例如,
auto_ptr< int > p1( new int( 1024) );
auto_ptr< int > p2 ( new int(2048) );
p1 = p2;
在赋值之前,p1指向的对象被删除,赋值之后,p1拥有int对象的所有权,而p2则不再拥有int对象的所有权。
auto_ptr类模板的几个方法
1. get()
操作get()返回auto_ptr对象内部的底层指针。例如:
auto_ptr< int > p_int_auto; //
if (p_int_auto.get() == 0)
; // p_int_auto没指向一个有效对象
由于p_int_auto没有初始化,故它的内部指针值班被设置为0,通过使用get()方法获取其内部的底层指针的值。
2. reset()
reset()操作可以设置一个auto_ptr对象的底层指针。例如:
p_int_auto.reset( new int( 1024 ) );
从auto_ptr的声明来看,我们不能在auto_ptr对象被定义后,再用new表达式创建对象的地址来直接向其赋值。为了重置一个auto_ptr对象,必须使用reset()操作。除了向reset()方法传递一个指针,也可以传递一个0值,这表示要取消原来的对象所有权。
3. release()
与 get()操作不同,release()操作除了返回底层对象的指针,还释放该对象的所有权。
例如:
auto_ptr< string > pstr_auto( new string (“a resource string”) );
auto_ptr< string > pstr_auto2< pstr_auto.release() );
通过第二个语句的操作,pstr_auto释放了自己对string对象的所有权,而pstr_auto2则拥有了string对象的所有权。
最新的C++标准,即C++11,虽然还保留了auto_ptr,但已标记为 deprecated (已废弃),并引入了新的unique_ptr作为auto_ptr的替代物。即使这样,通过了解autp_ptr,我们可以认识到资源管理的一些理念,比如以对象管理资源,比如RAII(Resource Acquisition Is Initialization),等等。这对于我们认识其他类型的智能指针也是大有裨益的,何乐而不为呢。
参考资料:
1.
C++ Primer 第三版
2.
Effective C++ 第三版
3.
auto_ptr 维基百科 http://en.wikipedia.org/wiki/Auto_ptr
以对象管理资源——C++智能指针auto_ptr简介的更多相关文章
- Effective C++ ----以对象管理资源
以对象管理资源 通过对象的析构函数的自动调用来自动释放资源 第一部分:几种典型的以对象管理资源的例子 1. STL::auto_ptr 获取资源后立刻放入资源管理对象 std::auto_ptr< ...
- [Effective C++ --013]以对象管理资源
这一节基本讲述的是将资源放进管理对象,防止忘记释放资源. 1.一般New和Delete使用场景 void fun() { SimpleClass* pSimpleClass1 = new Simple ...
- 《Effective C++》学习笔记条款13 以对象管理资源
条款 13 :以对象管理资源 例: voidf() { Investment *pInv = createInvestment(); ... ...
- C++ 智能指针auto_ptr
template<class T> class auto_ptr { public: ); // Item M5 有“explicitfor”// 的描述 template<clas ...
- 智能指针auto_ptr & shared_ptr
转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...
- Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为
三.资源管理 资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket ...
- effective C++ 读书笔记 条款14 以对象管理资源
如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...
- 关于智能指针auto_ptr
智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...
- C++智能指针 auto_ptr
C++智能指针 auto_ptr auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std. auto_ptr 适合用来管理生命周期比较短或者不 ...
随机推荐
- 进入MAC下面的Library目录
从LION后,苹果将library目录隐藏起来了,要进入那个目录,需要用到一定的技巧. 打开Finder,按下shift+command+g,输入“~/Library”(输入引号里面的),再按回车就到 ...
- Django的url解析
Django中采用正则表达式来匹配所请求的url,这个叫做URLconf,作为MVC中的C(控制器), 这样再调用相应的试图,达到控制器控制试图的显示的效果. 看一下Django的url解析过程 第一 ...
- c# winform 路径选择和文件读写
//读文件 private void readBtn_Click(object sender, EventArgs e) { try { if (pathTxt.Text == "" ...
- SmartGit 试用过期
smartgit是见过的最好用的git客户端, 要解决其试用版过期的问题,如下: 1.定位到文件夹 Windows: %APPDATA%\syntevo\SmartGit\OS X: ~/Librar ...
- 托管到GitHub
如何把项目托管到GitHub iOS开发拓展篇——如何把项目托管到GitHub 说明:本文主要介绍如何把一个OC项目托管到Github,重操作轻理论. 第一步:先注册一个Github的账号,这是必须的 ...
- HDU 3966 Aragorn's Story(树链剖分)
HDU Aragorn's Story 题目链接 树抛入门裸题,这题是区间改动单点查询,于是套树状数组就OK了 代码: #include <cstdio> #include <cst ...
- xhr的send方法以及node如何处理get和post数据
起因:看了阮一峰老师的关于上传文件的文章,进行测试,在使用xhr对象的send方法时遇到问题. 遇到的问题是使用send方法传送过去的数据,在node后台无法接收,经过很多次测试,怀疑是不是send与 ...
- Qt的setMouseTracking使用
bool mouseTracking 这个属性保存的是窗口部件跟踪鼠标是否生效. 如果鼠标跟踪失效(默认),当鼠标被移动的时候只有在至少一个鼠标按键被按下时,这个窗口部件才会接收鼠标移动事件. 如果鼠 ...
- Qt遍历图片文件
原地址:http://blog.sina.com.cn/s/blog_5c70dfc80100tgff.html //实现遍历某个文件下的图片文件 //如果想遍历其余类型文件,方法也一样,只需简单修改 ...
- PHP学习之-Mongodb在Windows下安装及配置
Mongodb在Windows下安装及配置 1.下载 下载地址:http://www.mongodb.org/ 建议下载zip版本. 2.安装 下载windows版本安装就和普通的软件一样,直接下一步 ...