Class auto_ptr

C++标准程序库提供的auto_ptr是一种智能型指针,帮助程序员防止“被异常抛出时发生资源泄漏”。注意我说的是“一种”智能型指针,现实生活中还有其他许多有用的智能型指针,auto_ptr只是针对某个特定问题而设计的,对于其他问题,auto-ptr无能为力。

一、auto_ptr的设计动机:
函数的操作经常需要依以下模式进行:
1、获取一些资源。
2、执行一些操作。
3、释放所获得的资源。
     假如函数一开始获得的资源被绑定在局部对象身上,当函数退出时,他们的析构函数被调用,从而自动释放这些资源。但是如果函数一开始获得的资源是以显式手法(比如说:new)获得,那就必须以显示手法(比如说:delete)释放。但是有时候会忘记delete或者异常一旦发生,函数立刻退出,根本执行不到函数尾端的delete语句,这就可能造成内存泄漏。当然你可以在函数中实现捕捉所有异常。但会使得函数变得十分复杂且容易出错。
    如果使用智能型指针能保证在任何一种情况下,只要自己被摧毁,就一定连带释放其所指的资源(因为智能型指针本来就是局部变量,所以无论是正常退出,还是异常退出,都能保证该指针被销毁从而释放资源)。

注意点:
    1、auto_ptr是这样一种指针:他是“他所指向的对象”的拥有者。所以,当身为对象拥有者的auto_ptr被摧毁时,该对象也将遭到摧毁。auto_ptr要求一个对象只能有一个拥有者。不再需要delete,也不再需要catch。
    2、auto_ptr拥有权是可以转移的:

std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2(ptr1);
或者
std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2;
ptr2 = ptr1;

在第一个语句中,ptr1拥有了那个new出来的对象。在 第二个语句中,拥有权由ptr1转交给ptr2。此后ptr2即拥有了那个new出来的对象,而ptr1不在拥有他。这样,对象就只会被delete一次(在ptr2被摧毁时)。
    如果ptr2在转交拥有权之前拥有另一个对象,则转交操作执行之前会先调用delete,将ptr2所拥有的对象先摧毁。

std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2(new ClassA);
ptr2 = ptr1; //ptr2之前拥有的对象被销毁,ptr1将第一个new出来的对象的拥有权转交给ptr2,ptr1为NULL。

    特殊用法:某个函数可以利用auto_ptr将拥有权转交给另一个函数。这种情况可能出现在两种情况:
        a、auto_ptr被以传值的方式被当作一个参数传递给某个函数。此时被调用函数的参数就获得了这个auto_ptr的拥有权。

void sink(std::auto_ptr<ClassA>);

    b、当auto_ptr被当作返回值返回时,将拥有权转交给调用端。

std::auto_ptr<ClassA> fun()
{
    std::auto_ptr<ClassA> ptr(new ClassA);
    ...
    return ptr;
}

void gun()
{
    std::auto_ptr<ClassA> ptr;
    for (int i=0; i<10; i++)
    {
        p = fun(); //一旦进入循环再次执行赋值动作,意味着ptr先前拥有的对象被销毁了。
        ...
    }
}

3、const std::auto_ptr<class T> ptr;ptr的拥有权不允许被转移。在这里,关键词const并非意味着你不能更改auto_ptr所拥有的对象,而是意味着你不能更改auto_ptr的拥有权。例如:

std::auto_ptr<int> f()
{
    const auto_ptr<int> p(new int);
    auto_ptr<int> q(new int);
    *p = 42;    //ok
    q = p;      //error
    p = q;      //error
    return p;   //error
}

4、并不存在针对array设计的auto_ptr。因为auto_ptr是透过delete而非delete[]来释放其所拥有的对象。
5、auto_ptr不满足STL标准容器的对其元素的要求。因为在拷贝和赋值动作之后,原本的auto_ptr和新产生的auto_ptr并不相等。原本的auto_ptr会交出拥有权,而不是拷贝给新的auto_ptr。
6、auto_ptr不是引用计数型的指针——这种指针保证,如果有一组智能型指针指向同一个对象,那么当且仅当最后一个智能型指针被注销时,该对象才会被摧毁。

运用实例:

#include <iostream>
#include <memory>
using namespace std;

template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
    if (NULL == p.get())
    {
        strm << "NULL";
    }
    else
    {
        strm << *p;
    }

    return strm;
}

int main()
{
    auto_ptr<int> p(new int(42));
    auto_ptr<int> q;

    cout << "after initialization:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;

    q = p;
    cout << "after assigning auto pointers:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;

    *q += 13;
    p = q;
    cout << "after change and reassignment:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;

    return 0;
}

注意:output操作符的第二个参数是一个const refernce,所以并没有发生拥有权的转移。
7、不能以一般指针的赋值手法来初始化一个auto_ptr:

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

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

下面一个例子展示const auto_ptr的特性:

#include <iostream>
#include <memory>
using namespace std;

template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
    if (NULL == p.get())
    {
        strm << "NULL";
    }
    else
    {
        strm << *p;
    }

    return strm;
}

int main()
{
    const auto_ptr<int> p(new int(42));
    const auto_ptr<int> q(new int(0));
    const auto_ptr<int> r;

    cout << "after initialization:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;
    cout << "r: " << r << endl;

    *q = *p;
    //*r = *p;    //ERROR:undefine behavior
    *p = -77;
    cout << "after assigning auto pointers:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;
    cout << "r: " << r << endl;

    //q = p;    //ERROR at compile time
    //r = p;    //ERROR at compile time

    return 0;
}

注意下列赋值操作是错误的:
    *r = *p;
这个句子对于一个“未指向任何对象”的auto_ptr进行提领操作。C++标准规定,这会导致未定义行为,比如说导致程序的崩溃。

转载于:https://my.oschina.net/u/2515635/blog/780001

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值