Chinaunix首页 | 论坛 | 博客
  • 博客访问: 202415
  • 博文数量: 70
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 412
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-30 11:07
文章分类

全部博文(70)

文章存档

2014年(68)

2013年(2)

我的朋友

分类: C/C++

2014-04-24 11:01:25

1.为什么称它为“自动”指针?
auto_ptr只是众多可能的智能指针之一。许多商业库提供了更复杂的智能指针,用途广泛而令人惊异,从管理引用的数量到提供先进的代理服务。可以把标准C++ auto_ptr看作智能指针的Ford Escort(elmar注:可能指福特的一种适合家居的车型):一个简易、通用的智能指针,它不包含所有的小技巧,不像专用的或高性能的智能指针那么奢华,但是它可以很好的完成许多普遍的工作,它很适合日常性的使用。

auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理。这里是一个简单的代码示例,没有使用auto_ptr所以不安全:
 

1, auto_ptr类

auto_ptr是一个模板类,定义如下:

template <typename Type>
class auto_ptr {...};

它存储的是一个指向Type的指针。

顾名思义,auto_ptr是一种智能指针,它包含一个动态分配内存的指针,并在它生命周期结束的时候,销毁包含的指针所指向的内存。


例1:


     void f()

    {

        Type* pt(new Type);

        //一些代码...

        delete pt;
    }

这样的代码很常见,但它有可能造成内存泄露。首先你用了new,你就要记得用delete,但即使你记住了用delete,还是会出问题。如果f()在执行delete pt之前,就抛出了异常,函数返回了。那么这个分配的对象就没被删除。


使用auto_ptr,很优雅的解决了这些问题。

例2:

         void f()

        {

              auto_ptr pt(new Type);

              //一些代码...
        }

现在的代码,不会泄露Type类型的对象。不管是函数正常结束,还是抛出异常结束,pt的析构函数总是会在出栈时被调用。清理分配的对象会自动进行。

2, auto_ptr构造函数

构造函数1:explicit auto_ptr(Type* _Ptr = 0) throw( );

 

            auto_ptr<int> pt;                           //包含一个int*的指针,并初始化为NULL

            auto_ptr<int> pt(new int(123)); //包含一个int*的指针,并初始化为123的地址

            auto_ptr<int> pt = new int(123); //error!构造函数声明为explicit

 


构造函数2:auto_ptr(auto_ptr& _Right) throw( );

 

            int* ptr = new int();

            auto_ptr<int> pt1(ptr); //构造函数1

            auto_ptr<int> pt2(pt1); //将pt1的使用权转给pt2,注意pt1指向NULL了

                                    //pt1调用了本身的release()函数,将内部指针地址传给pt2
 // 使用auto_ptr就像我们以前使用简单指针一样
      *pt2 = 12;       // 就像 "*pt1 = 12;"
      pt2->SomeFunc(); // 就像 "pt1->SomeFunc();"


      // 用get()来获得指针的值
      assert( pt1 == pt2.get() );


      // 用release()来撤销所有权
      T* pt3 = pt2.release();


      // 自己删除这个对象,因为现在
      // 没有任何auto_ptr拥有这个对象
      delete pt3;


    // pt2不再拥有任何指针,所以不要
      // 试图删除它...ok,不要重复删除

构造函数3:template<typename Other>       

                auto_ptr(auto_ptr& _Right) throw( );

                          声明这样一个拷贝构造函数的目的,就是为了派生类指针能转换成基类的指针。

例:

      class Base { };

      class Derived : public Base { };

      auto_ptr pDerived(new Derived);

      auto_ptr    pBase(pDerived);           //让这样的代码能通过编译器

           其本质是为了让,auto_ptr类内部的Derived*转换为Base* 


构造函数4:auto_ptr(auto_ptr_ref _Right) throw( );

                        //暂略

3, auto_ptr成员函数

成员函数1:Type* get( ) const throw( );

                    获得包含指针的地址

                   int* ptr = new int(123);

                   auto_ptr pt(ptr);

                   assert(pt.get() == ptr); //相等,指向同一地址

成员函数2:Type* release( ) throw( );

                    返回包含指针的地址,并将包含指针设为NUll

                   string* pstr = new string("hello");

                   auto_ptr pt(pstr);

                   pt.release();   //不在指向string对象

                                       //此时,pt.get()等于NULL

                   delete pstr;    //应该手动删除pstr指向的内存块 

成员函数3:void reset(Type* _Ptr = 0);

                   double* pdouble1 = new double(3.14);

                   double* pdouble2 = new double(1.23);

                   auto_ptr pt1(pdouble1);

                   pt1.reset(pdouble2);  //将删除pt1所指向的内存块就是pdouble1指向的那块


                                                 //此时,pt.get()等于pdouble2


                   cout << *pdouble1;   //error,pdouble已经是野指针了           


4, 使用总结

1,auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。

2,auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。

3,两个auto_ptr对象不会同时指向同一块内存块。要明白2个auto_ptr对象赋值会发生什么。

4,千万不要把auto_ptr对象放在容器中。

5,当将auto_ptr作为函数参数时,最好声明为const auto_ptr&(by const ref).当函数返回值可以简单的传值(by value).


阅读(703) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~