以对象管理资源——C++智能指针auto_ptr简介

标签: auto_ptr 智能指针 C++11
1422人阅读 评论(0) 收藏 举报
分类:

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类模板的几个方法

从auto_ptr类模板的声明可以看到,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
查看评论

血腥大地-第二季(资源破解与管理)

课程继承<血腥大地>游戏内容 1.主要完成游戏资源的获取,从原血腥大地游戏中获取(不涉及任何商业利益,不能将游戏资源用于其他商业游戏). 2.游戏资源的整理以及优化 3.游戏纹理资源打包工具的制作 4.游戏字体资源打包制作工具
  • 2017年03月11日 22:09

C++11 智能指针——(C++98)auto_ptr

auto_ptr是严格的拥有权类智能指针,使用时注意以下几点 绝对不应使用一个原始指针来初始化2个或2个以上的auto_ptr对象 auto_ptr对象通过赋值或构造转移拥有权,一旦...
  • wssjlrw
  • wssjlrw
  • 2016-03-05 13:39:54
  • 712

智能指针auto_ptr、内存泄漏解决

在C++11中,已经不使用auto_ptr,而用 unique_ptr进行替代,不过二者原理都差不多。头文件:memory智能指针:实质上是一个类,在创建智能指针的时候,本质上是在栈上创建了一个对象...
  • wang664626482
  • wang664626482
  • 2016-08-29 20:02:14
  • 950

我所熟悉的C++智能指针auto_ptr vs shared_ptr (一)

在开发过程中,曾经使用过两种C++的智能指针,如今,便总结一下,顺便比较比较二者使用中的区别,注意避免入坑的危险。:-D 我们知道,在C++中,如果创建一个指向某个对象的指针,那么在使用完这个对象...
  • u013700658
  • u013700658
  • 2015-10-28 09:24:43
  • 1564

c++智能指针:auto_ptr shared_ptr

1. 简介 C++程序员最痛苦的莫过于对内存的管理,由于没有像C# 和 java的内存回收机制,C++程序员在复杂的程序中容易造成内存的泄露。即使程序员十分小心,异常的产生也有可能会造成部分内存的泄...
  • gui694278452
  • gui694278452
  • 2015-06-03 18:44:10
  • 3028

c++中的智能指针auto_ptr解析

c++中的auto_ptr是一个类,却可以像指针一样去使用。使用auto_ptr需要包含头文件#include 例如:auto_ptr ps(new string("hello"));可以像指针一样...
  • uestclr
  • uestclr
  • 2016-05-06 10:56:26
  • 2081

C++中智能指针std::auto_ptr的用法详解

C++中指针申请和释放内存通常采用的方式是new和delete。然而标准C++中还有一个强大的模版类就是auto_ptr,它可以在你不用的时候自动帮你释放内存。下面简单说一下用法。...
  • xiaoluer
  • xiaoluer
  • 2017-02-09 15:23:08
  • 1123

STL中的智能指针(Smart Pointer)及其源码剖析: std::auto_ptr

STL中的智能指针(Smart Pointer)及其源码剖析: std::auto_ptr 本文主要介绍了 auto_ptr的使用及其源码。 auto_ptr是STL中的智能指针家族的成员之一, ...
  • yanglingwell
  • yanglingwell
  • 2017-02-20 12:22:09
  • 11510

智能指针:从std::auto_ptr到std::unique_ptr

std::auto_ptr封装动态申请对象内存返回的指针,并且其行为也和普通指针一样。最重要的一点,程序员不必记得去释放之前申请的内存,当std::auto_ptr销毁时,其封装的指针所指向的内存也会...
  • hanhuili
  • hanhuili
  • 2012-12-15 21:38:43
  • 5727

[C++]资源管理

资源管理 所谓资源就是,一旦使用了它,将来必须归还给系统!C++最常见的资源就是动态分配内存,如果不归还就会内存泄露。 1. 以对象管理资源 我们通常希望有一个对象来帮助我们解决资源管理的问题...
  • stary_yan
  • stary_yan
  • 2016-04-26 23:21:15
  • 5017
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 77万+
    积分: 6783
    排名: 4335
    博客专栏
    最新评论