智能指针(一)auto_ptr

本文回顾了C++98中的auto_ptr类,探讨其在C++11后的变迁,重点讲解了赋值操作中的权限转移、内存安全问题以及容器支持的局限。析构函数导致的同一内存不能被同时拥有,以及auto_ptr在容器使用和参数传递上的限制都被详细阐述。
摘要由CSDN通过智能技术生成

总结

1、C++98中引入,C++11中弃用,C++17中被移除
2、赋值时权限转移,因为赋值运算符重载导致,简单理解就是在赋值时,他先把自己的指针给别人,然后把自己设置成null , 相当于国家军委主席权利交接,一旦交出去自己就没有权利调用军队了;
3、不能指向同一个内存,析构函数导致
4、容器不能很好的支持auto_ptr类。容器内元素的类型约束为元素类型必须支持赋值运算(引用不支持赋值,所以引用类型不能被放入容器)
5、不能作为参数传递,引用和指针可以;

代码

Auto_ptr源码:

template <class _Ty>
class auto_ptr { // wrap an object pointer to ensure destruction
public:
    using element_type = _Ty;

    explicit auto_ptr(_Ty* _Ptr = nullptr) noexcept : _Myptr(_Ptr) {}

    auto_ptr(auto_ptr& _Right) noexcept : _Myptr(_Right.release()) {}

    auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept {
        _Ty* _Ptr   = _Right._Ref;
        _Right._Ref = nullptr; // release old
        _Myptr      = _Ptr; // reset this
    }

    template <class _Other>
    operator auto_ptr<_Other>() noexcept { // convert to compatible auto_ptr
        return auto_ptr<_Other>(*this);
    }

    template <class _Other>
    operator auto_ptr_ref<_Other>() noexcept { // convert to compatible auto_ptr_ref
        _Other* _Cvtptr = _Myptr; // test implicit conversion
        auto_ptr_ref<_Other> _Ans(_Cvtptr);
        _Myptr = nullptr; // pass ownership to auto_ptr_ref
        return _Ans;
    }

    template <class _Other>
    auto_ptr& operator=(auto_ptr<_Other>& _Right) noexcept {
        reset(_Right.release());
        return *this;
    }

    template <class _Other>
    auto_ptr(auto_ptr<_Other>& _Right) noexcept : _Myptr(_Right.release()) {}

    auto_ptr& operator=(auto_ptr& _Right) noexcept {
        reset(_Right.release());
        return *this;
    }

    auto_ptr& operator=(auto_ptr_ref<_Ty> _Right) noexcept {
        _Ty* _Ptr   = _Right._Ref;
        _Right._Ref = 0; // release old
        reset(_Ptr); // set new
        return *this;
    }

    ~auto_ptr() noexcept {
        delete _Myptr;
    }

    _NODISCARD _Ty& operator*() const noexcept {
#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Myptr, "auto_ptr not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return *get();
    }

    _NODISCARD _Ty* operator->() const noexcept {
#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Myptr, "auto_ptr not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return get();
    }

    _NODISCARD _Ty* get() const noexcept {
        return _Myptr;
    }

    _Ty* release() noexcept {
        _Ty* _Tmp = _Myptr;
        _Myptr    = nullptr;
        return _Tmp;
    }

    void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer
        if (_Ptr != _Myptr) {
            delete _Myptr;
        }

        _Myptr = _Ptr;
    }

private:
    _Ty* _Myptr; // the wrapped object pointer
};

比较重要的函数如下,我们只要研究以下函数即可:

//构造函数
    explicit auto_ptr(_Ty* _Ptr = nullptr) noexcept : _Myptr(_Ptr) {}
//拷贝构造函数
auto_ptr(auto_ptr& _Right) noexcept : _Myptr(_Right.release()) {}
//赋值运算符重载
    auto_ptr& operator=(auto_ptr& _Right) noexcept {
        reset(_Right.release());
        return *this;
    }
//析构函数
    ~auto_ptr() noexcept {
        delete _Myptr;
    }
//release函数,release函数太骚了
//先用一个临时变量保存原有指针,然后将_Myptr设置成null,最后返回临时变量
    _Ty* release() noexcept {
        _Ty* _Tmp = _Myptr;
        _Myptr    = nullptr;
        return _Tmp;
    }

//重置函数
    void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer
        if (_Ptr != _Myptr) {
            delete _Myptr;
        }

        _Myptr = _Ptr;
    }

3、不能指向同一个内存,析构函数导致

int main()
{
    int* p = new int(12);
    auto_ptr<int> aptr1(p);
    auto_ptr<int> aptr2(p);

    return 0;
    //在析构的时候aptr1会把p的内存delete掉,aptr2再次去delete p的内存的时候就会出现问题
}

总结

重要的总结再重申一遍
1、C++98中引入,C++11中弃用,C++17中被移除
2、赋值时权限转移,因为赋值运算符重载导致,简单理解就是在赋值时,他先把自己的指针给别人,然后把自己设置成null , 相当于国家军委主席权利交接,一旦交出去自己就没有权利调用军队了;
3、不能指向同一个内存,西沟函数导致
4、容器不能很好的支持auto_ptr类。容器内元素的类型约束为元素类型必须支持赋值运算(引用不支持赋值,所以引用类型不能被放入容器)
5、不能作为参数传递,引用和指针可以;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值