现在的位置: 首页 > 综合 > 正文

C++中STL的auto_ptr

2013年04月15日 ⁄ 综合 ⁄ 共 3486字 ⁄ 字号 评论关闭

1. STLauto_ptr

看下面情况

    string * pstr = new string;
    g();            // 如果 g 掷出一个异常,内存溢出
delete pstr;    // 如果 g 掷出一个异常,则此行为不能达到的代码行。
那就不能delete pstr.
try … catch ?
try
{
    string * pstr = new string;
    g();            // 如果 g 掷出一个异常,内存溢出
delete pstr;    // 如果 g 掷出一个异常,则此行为不能达到的代码行。
}
catch(…)
{
     // 这个局部空间中没有pstr.
}
 
于是就有了

auto_ptr

 

#include <memory>          // 注意头文件
#include <string>
using namespace std;
void func()
{
    auto_ptr<string> pstr (new string); /* 创建并初始化auto_ptr */

}

 

2. auto_ptr 要注意的问题

1.    auto_ptr重载了操作符&,*->。不要被语法误导,记住pstr是一个对象,不是一个指针。只是它重载了这些操作符后, 使用上相指针一样.

2.    不要将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做,否则可能会碰到不可预见的结果

3.    不要将数组作为auto_ptr的参数, 可以理解到在auto_ptr, 使用delete, 但没有使用delete [].

4. auto_ptr不能作为容器的成员。

5. 不能通过赋值操作来初始化auto_ptr

std::auto_ptr<int> p(new int(42));     // OK

std::auto_ptr<int> p = new int(42);    // ERROR

这是因为auto_ptr 的构造函数被定义为了explicit

 

3. 智能指针的引用计数与拥有权问题

看这段代码:

#include "stdafx.h"

#include <memory>

#include <iostream>

 

class CTest

{

private:

     int m_nData;

public:

     CTest(int nData = 0)

         : m_nData(nData)

     {

 

     }

     ~CTest(){}

public:

     void Show()

     {

         std::cout << m_nData << std::endl;

     }

};

 

void FunFirst(std::auto_ptr< CTest > pA)

{

     pA->Show();

};

 

int _tmain(int argc, _TCHAR* argv[])

{

     std::auto_ptr< CTest > pA( new CTest(5));   

     FunFirst( pA );

     pA->Show();

     return 0;

}

 

 

表面上看好像没有问题, 但是看一下

void FunFirst(std::auto_ptr< CTest > pA);

FunFirst( pA );    // 这里调用的时候, 会使用auto_ptr的构造函数

                   // auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()

                  //   : _Myptr(_Right.release())

                  // { // construct by assuming pointer from _Right auto_ptr

                  // }

                   // 在这个构造函数中, 调用了 auto_ptr::release()

                   //   _Ty *release() _THROW0()

                  // { // return wrapped pointer and give up ownership

                  //       _Ty *_Tmp = (_Ty *)_Myptr;

                  //       _Myptr = 0;            // 这里是关键 _Myptr被清0.

                  //       return (_Tmp);

                  // }

那在FunFirst( pA );下面的pA->Show();, pA中的_Myptr已经被清0, 再调用Show就会报错.

 

void FunFirst(std::auto_ptr< CTest > pA)改为

void FunFirst(const std::auto_ptr< CTest >& pA)即可

 

以上这段代码就是关于智能指针的实现问题: 如果智能指针的实现是使用引用计数的话, 以上代码将不会报错, stl中的auto_ptr是使用拥有权去实现, 拥有权给了别人之后, 就不能再使用了.

 

再看下面代码

// 示例2: 使用一个auto_ptr

void g()

{

     CTest* pt1 = new CTest;

     // 现在,我们有了一个分配好的对象

     // 将所有权传给了一个auto_ptr对象

     auto_ptr<CTest> pt2( pt1 );     

     // 使用auto_ptr就像我们以前使用简单指针一样

     *pt2 = 12;       // 就像"*pt1 = 12;"

     pt2->SomeFunc(); // 就像"pt1->SomeFunc();"

     // get()来获得指针的值

     assert( pt1 == pt2.get() );

     // release()来撤销所有权

     CTest* pt3 = pt2.release();

     // 自己删除这个对象,因为现在

     // 没有任何auto_ptr拥有这个对象

     delete pt3;

     // pt2不再拥有任何指针,所以不要

     // 试图删除它...ok,不要重复删除

}

 

 

// 最后,我们可以使用auto_ptrreset()函数来重置auto_ptr使之拥有另一个对象。

// 如果这个auto_ptr已经拥有了一个对象,那么,它会先删除已经拥有的对象,

// 因此调用reset()就如同销毁这个auto_ptr,然后新建一个并拥有一个新对象:

// 示例3: 使用reset()

//

void h()

{

     auto_ptr<CTest> pt( new CTest(1) );

     pt.reset( new T(2) );

     // 删除由"new T(1)"分配出来的第一个T

     // 最后,pt出了作用域,

     // 第二个T也被删除了

}

 

2. boost 的智能指针实现

scoped_ptr            <boost/scoped_ptr.hpp>              简单的单一对象的唯一所有权。不可拷贝。

scoped_array         <boost/scoped_array.hpp>           简单的数组的唯一所有权。不可拷贝。

shared_ptr             <boost/shared_ptr.hpp>               在多个指针间共享的对象所有权。

shared_array          <boost/shared_array.hpp>            在多个指针间共享的数组所有权。

weak_ptr               <boost/weak_ptr.hpp>                 一个属于 shared_ptr 的对象的无所有权的观察者。

intrusive_ptr          <boost/intrusive_ptr.hpp>             带有一个侵入式引用计数的对象的共享所有权。

 

1. shared_ptrBoost库所提供的一个智能指针的实现,shared_ptr就是为了解决auto_ptr在对象所有权上的局限性(auto_ptr是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针.

2. shared_ptrauto_ptr更安全

3. shared_ptr是可以拷贝和赋值的,拷贝行为也是等价的,并且可以被比较,这意味这它可被放入标准库的一般容器(vectorlist)和关联容器中(map)。

关于shared_ptr的使用其实和auto_ptr差不多,只是实现

抱歉!评论已关闭.