zoukankan      html  css  js  c++  java
  • C++智能指针 auto_ptr

    C++智能指针 auto_ptr

    auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std.
    auto_ptr 适合用来管理生命周期比较短或者不会被远距离传递的动态对象, 最好是局限于某个函数内部或者是某个类的内部.

    使用方法:
      std::auto_ptr<int> pt(new int(10));
      pt.reset(new int(11));

    成员函数

      3个重要的函数:
      (1) get 获得内部对象的指针, 由于已经重载了()方法, 因此和直接使用对象是一样的.如 auto_ptr <int> sp(new int(1)); sp 与 sp.get()是等价的
      (2) release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放
        std::auto_ptr<int> ap0(new int(1));
        int* pa = ap0.release();
        delete pa; // 需要手动释放
      (3) reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权)

      其构造函数被声明为 explicit, 因此不能使用赋值符对其赋值(即不能使用类似这样的形式 auto_ptr<int> p = new int;)

    auto_ptr 的特征

    (1) auto_ptr 的对象所有权是独占性的.
      auto_ptr 的拷贝构造和赋值操作符所接受的参数类型都是非const的引用类型(而一般都应该使用的const引用类型), 其原因在于为了使其内部能调用了 release 方法将原有的对象进行释放, 然后使用新对象替换原有的对象.
      因此导致动态对象的所有权被转移了, 新的 auto_ptr 独占了动态对象的所有权. 被拷贝对象在拷贝过程中被修改, 拷贝物与被拷贝物之间是非等价的.
      下面的使用方法将会出错:
        std::auto_ptr<int> pt1(new int(10));
        std::auto_ptr<int> pt2 = pt1;
        printf("pt1:%d ", pt1); // 此时应输出 0
        printf("pt1 value:%d ", *pt1); // 错误, 对象已释放
    (2) 不能将 auto_ptr 放入到标准容器中. 标准库容器无准备的拷贝行为, 会导致原 auto_ptr 内的对象被释放, 造成难以发觉的错误.

     

    使用 auto_ptr 的注意事项

    (1) auto_ptr 不能指向数组
    (2) auto_ptr 不能共享所有权
    (3) auto_ptr 不能通过复制操作来初始化
    (4) auto_ptr 不能放入容器中使用
    (5) auto_ptr 不能作为容器的成员
    (6) 不能把一个原生指针给两个智能指针对象管理(对所有的智能指针).
      int* p = new int;
      auto_ptr<int> ap1(p);
      auto_ptr<int> ap2(p); // 错误, p不能给第二个智能指针对象. 会引起两次释放p

     

    VC中的源码实现

    template<class _Ty>
    class auto_ptr
    {    // wrap an object pointer to ensure destruction
    public:
        typedef auto_ptr<_Ty> _Myt;
        typedef _Ty element_type;
    
        explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
            : _Myptr(_Ptr)
        {    // construct from object pointer
        }
    
        auto_ptr(_Myt& _Right) _THROW0()
            : _Myptr(_Right.release())
        {    // construct by assuming pointer from _Right auto_ptr
        }
    
        auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
        {    // construct by assuming pointer from _Right auto_ptr_ref
            _Ty *_Ptr = _Right._Ref;
            _Right._Ref = 0;    // release old
            _Myptr = _Ptr;    // reset this
        }
    
        template<class _Other>
        operator auto_ptr<_Other>() _THROW0()
        {    // convert to compatible auto_ptr
            return (auto_ptr<_Other>(*this));
        }
    
        template<class _Other>
        operator auto_ptr_ref<_Other>() _THROW0()
        {    // convert to compatible auto_ptr_ref
            _Other *_Cvtptr = _Myptr;    // test implicit conversion
            auto_ptr_ref<_Other> _Ans(_Cvtptr);
            _Myptr = 0;    // pass ownership to auto_ptr_ref
            return (_Ans);
        }
    
        template<class _Other>
        _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()
        {    // assign compatible _Right (assume pointer)
            reset(_Right.release());
            return (*this);
        }
    
        template<class _Other>
        auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
            : _Myptr(_Right.release())
        {    // construct by assuming pointer from _Right
        }
    
        _Myt& operator=(_Myt& _Right) _THROW0()
        {    // assign compatible _Right (assume pointer)
            reset(_Right.release());
            return (*this);
        }
    
        _Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
        {    // assign compatible _Right._Ref (assume pointer)
            _Ty *_Ptr = _Right._Ref;
            _Right._Ref = 0;    // release old
            reset(_Ptr);    // set new
            return (*this);
        }
    
        ~auto_ptr()
        {    // destroy the object
            delete _Myptr;
        }
    
        _Ty& operator*() const _THROW0()
        {    // return designated value
    #if _ITERATOR_DEBUG_LEVEL == 2
            if (_Myptr == 0)
                _DEBUG_ERROR("auto_ptr not dereferencable");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
    
            return (*get());
        }
    
        _Ty *operator->() const _THROW0()
        {    // return pointer to class object
    #if _ITERATOR_DEBUG_LEVEL == 2
            if (_Myptr == 0)
                _DEBUG_ERROR("auto_ptr not dereferencable");
    #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
    
            return (get());
        }
    
        _Ty *get() const _THROW0()
        {    // return wrapped pointer
            return (_Myptr);
        }
    
        _Ty *release() _THROW0()
        {    // return wrapped pointer and give up ownership
            _Ty *_Tmp = _Myptr;
            _Myptr = 0;
            return (_Tmp);
        }
    
        void reset(_Ty *_Ptr = 0)
        {    // destroy designated object and store new pointer
            if (_Ptr != _Myptr)
                delete _Myptr;
            _Myptr = _Ptr;
        }
    
    private:
        _Ty *_Myptr;    // the wrapped object pointer
    };

     

     

     

  • 相关阅读:
    最优匹配问题
    树的最大独立集
    koa2学习(一)
    vue源码阅读(一)
    一直以为错的一个问题,记录一下
    关于 vuex 的使用忠告
    《javascript设计模式与开发实践》--- (单一职责原则)
    心累
    node 学习(二)
    node 学习(一)
  • 原文地址:https://www.cnblogs.com/diysoul/p/5930341.html
Copyright © 2011-2022 走看看