已经消失的智能指针——auto_ptr

动态内存的管理是通过一对运算符来完成的:

  • new,在动态内存中为对象分配空间并返回一个指向改该对象的指针。
  • delete,接收一个动态对象的指针,销毁该对象,并释放与之关联的内存。

出现问题:不能确保在正确的时间释放它:

  • 有时候我们会忘记释放内存,这种情况下会产生内存泄漏
  • 有时候再尚有指针引用内存的时候指针被释放了

因此就出现了智能指针,帮助我们进行指针的释放。


auto_ptr的使用

auto_ptr就是第一个,但是由于其中的问题现在没有了

auto_ptr使用方法:

  1. 在构造时获取对某个对象的所有权(ownership),
  2. 在析构时释放该对象。

上面说的是构造和析构,此时就出现了问题,如果两个析构同时指向一个对象,那么当一个析构之后,另一个析构就发现没有对象了,自然就出现了问题:

如下:

       { int *a = new int(10);
        auto_ptr<int> b(a);
        auto_ptr<int> c(a);}

此时这个大括号作用域结束之后,b对象调用析构之后,就将a删除了,此时c再调用析构就会发生错误了

第一个问题:
所以我们需要注意了,两个auto_ptr不能同时拥有同一个对象。


拷贝构造与赋值

auto_ptr要求其对“裸”指针的完全占有性,也就是说一个“裸”指针不能同时被两个以上的auto_ptr所拥有。

扫描二维码关注公众号,回复: 12473194 查看本文章

因此,在拷贝构造或赋值操作时,auto_ptr的做法是“所有权转移”,即拷贝或赋值的源对象将失去对“裸”指针的所有权。

  1. 这种方法虽然避免了第一个问题,析构的时候不会出现一个指针析构时发现对象已经被析构的问题。
  2. 但是一个auto_ptr被拷贝或被赋值后,其已经失去对原对象的所有权,如果再对这个指针进行操作则是不安全的。

如下:

        int*p = new int(0); 
        auto_ptr<int>ap1(p); 
        auto_ptr<int>ap2 = ap1; 
        cout << *ap1;

此时ap1已经失去了p的使用权,因此就会出现错误。

这种情况较为隐蔽的情形出现在将auto_ptr作为函数参数按值传递,因为在函数调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造).

如下:

void show(auto_ptr<int>ap)
{

    cout << *ap;
}

int main()
{

    int*p = new int(0);
    auto_ptr<int>ap1(p);
    show(ap1);
    cout << *ap1;

此时ap1已经失去了所有权,所以也会错误。

第二个问题:
避免进行拷贝构造与赋值发生错误。


auto_ptr常用的成员函数

1) get()

  1. 第一行与第三行相同,都是int所在的那块内存的地址。
  2. 第二行是ap1这个类对象本身所在内存的地址。

2) reset()

重新设置auto_ptr指向的对象。

类似于赋值操作,但赋值操作不允许将一个普通指针指直接赋给auto_ptr,而reset()允许。如下例:

    auto_ptr<int> a(new int(1));
    a.reset(new int(2));

在例子中,重置前a拥有“ 1 ”内存的所有权,这块内存首先会被释放。之后a再拥有" 2 "字符内存的所有权。


3) release()

返回auto_ptr指向的那个对象的内存地址,并释放对这个对象的所有权。

用此函数初始化auto_ptr时可以避免两个auto_ptr对象拥有同一个对象的情况(与get函数相比)。

例子如下:

    {
        auto_ptr<int> a(new int(1));
        auto_ptr<int> b(a.release());
    }

猜你喜欢

转载自blog.csdn.net/qq_46423166/article/details/113764347