智能指针基础

为什么需要智能指针:

因为动态开辟的内存过早,过晚释放都不好,不是放,就会导致内存泄漏------内存被占用,导致无法使用。

智能指针------自动释放所指对象。

智能指针的本质

模板

建立一个类把指针封装起来

智能指针实现原理

链接

简单实现,也容易看懂---链接

智能指针使用的是浅拷贝

当引用计算为0时,需要释放至少两个对象:1,引用计数 2,指针所指对象。

unique_ptr:

一个unique_ptr智能指针独享一个指针对象的所有权,当这个智能指针被赋值时,对象的所有权转移,当智能指针被销毁时,智能指针指向的对象也会被销毁。

可独享的原理:

独享,不可复制:

禁用拷贝构造函数和=重载运算符。

	unique_ptr(const unique_ptr<T>&) noexcept = delete;
	unique_ptr& operator = (const unique_ptr&) noexcept = delete;

把两种赋值函数,都设置为delete。
使用"=delete"修饰,表示函数被定义为deleted,也就意味着这个成员函数不能再被调用,否则编译就会出错。

noexcept

以下是不允许的:

为什么可以用=来实现初始化

unique_ptr<int> inst1=unique_ptr<int>(new int);

右边的对象(包括noew出来的对象)为右值,调用的是移动拷贝构造函数。

可转移-move

不可以拷贝,但是可以转移指针对象的所有权,利用了移动拷贝构造函数和参数为右值引用的的=重载函数,所以需要转移所有权的时候需要使用move函数将原来的智能指针转为右值引用,传入到新的智能指针中进行转移。

    unique_ptr(unique_ptr&& move) noexcept
	{
        std::cout << "construct for unique_ptr&&" << std::endl;
		move.swap(*this);
	}
	unique_ptr& operator=(unique_ptr&& move) noexcept
	{
		move.swap(*this);
		return *this;
	}
	// swaps the resources 将右值引用指向的对象转移给自己
	void swap(unique_ptr<T>& resource_ptr) noexcept
	{
		std::swap(ptr_resource, resource_ptr.ptr_resource);
	}

以下是允许的:

    unique_ptr<Test> tPtr1(new Test());
    //以下两句话就允许,因为pPtr1做了控制权转移
    unique_ptr<Test> tPtr3(std::move(tPtr1));
    unique_ptr<Test> tPtr4 = std::move(tPtr3);

链接

怎么去除unique_ptr使用

使用unique_ptr的指针或者引用:

std::unique_ptr<Request>& send_request=queue_.front();

不要尝试去除unique_ptr赋给另一个:

shared_ptr:

浅拷贝

不能使用原始指针创建不同的共享指针

链接

make_shared<>()

注意:make_shared不需要再new了,()是用来传输构造函数需要的参数的

shared_ptr初始化

weak_ptr--弱智能指针

1,需要共享智能指针初始化

2,使用通过lock函数检测,指向对象存在则返回一个共享智能指针,使用这个共享智能指针。

3,已经有shared_ptr,为什么还要weak_ptr----连接

(1)用来观察shared_ptr智能指针对象,比如通过弱智能指针的lock或者expird函数可以判断shared_ptr对象是否还存在,通过use_count()判断共享智能指针的引用计数。

(2)最重要的是弱智能指针可以解决共享指针出现的引用计数增加的问题,有时候我们只需要获取对象,不需要增加对象的引用计数时,就需要使用弱智能指针。

(3)和共享指针一起用来解决原始指针循环引用出现的释放内存奔溃的现象和共享指针循环引用出现的无法释放内存的现象。

原始指针循环引用----本来只想释放一个对象的内存,但是却因为相互引用,导致同时想要销毁另一个对象内存,出现奔溃。

共享指针循环引用---开辟的外部对象可以释放,但是内部成员对象没有释放,引用计数还是1,释放不了成员对象,开辟的内存还在。

weak_ptr函数

智能指针比较

指针unique_ptrshared_ptrweak_ptr
功能一个指针独享一个对象共享对象借用共享智能指针对象,
引用计数1增加不改变shared_ptr的引用计数
初始化

unique_ptr<string> up(new string("yuvcsdc"));

//unique_ptr不支持拷贝

1,

shared_ptr<string> sp(new string("yuvcsdc"));

2,

auto p=make_shared<int>(100);

拷贝:shared_ptr<int> pp(p);

建立时需要用共享智能指针来初始化它:

auto p=make_shared<int>(42);

weak_ptr<int> wp(p);

调用对象可能不存在,先成员函数lock判断,lock返回一个shared_ptr对象

智能指针初始化

智能指针是指针,不能直接利用数据赋值,要利用指针(地址)赋值

shared_ptr<int> p(100);//错
shared_ptr<int> p(new int(100));//对

智能指针的引用计数怎么实现的(计数器存放在哪)

建立另一个类对象来作为计数器,统计引用计数。通过浅拷贝的方式来获取引用计数对象的地址,然后修改这计数器的值。

智能指针函数

unique_ptr

shared_ptr

 

use_count()-----计算引用计数

 源码

unique_ptr

template <typename _Tp, typename _Dp = default_delete<_Tp> >
class unique_ptr
{
    class _Pointer
    {
        template<typename _Up>
        static typename _Up::pointer __test(typename _Up::pointer*);

        template<typename _Up>
        static _Tp* __test(...);

        typedef typename remove_reference<_Dp>::type _Del;

    public:
        typedef decltype(__test<_Del>(0)) type;
    };

    typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
    __tuple_type _M_t;

public:
    typedef typename _Pointer::type   pointer;
    typedef _Tp                       element_type;
    typedef _Dp                       deleter_type;

    constexpr unique_ptr() noexcept
        :_M_t()
    { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); }

    explicit unique_ptr(pointer __p) noexcept
        :_M_t(__p, deleter_type())
    { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); }

    unique_ptr(pointer __p, typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept
        :_M_t(__p, __d)
    {
    }

    unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d) noexcept
        :_M_t(std::move(__p), std::move(__d))
    { static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); }


    constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }

    unique_ptr(unique_ptr&& __u) noexcept
        :_M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
    {
    }

    template<typename _Up, typename _Ep, typename = _Require<is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, __not_<is_array<_Up>>, typename conditional<is_reference<_Dp>::value, is_same<_Ep, _Dp>, is_convertible<_Ep, _Dp>>::type>>
    unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
        :_M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    {
    }

    ~unique_ptr() noexcept
    {
        auto& __ptr = std::get<0>(_M_t);
        if (__ptr != nullptr)
            get_deleter()(__ptr);
        __ptr = pointer();
    }

    unique_ptr& operator=(unique_ptr&& __u) noexcept
    {
        reset(__u.release());
        get_deleter() = std::forward<deleter_type>(__u.get_deleter());
        return *this;
    }

    template<typename _Up, typename _Ep>
    typename enable_if< __and_<is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, __not_<is_array<_Up>>>::value, unique_ptr&>::type
    operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
    {
        reset(__u.release());
        get_deleter() = std::forward<_Ep>(__u.get_deleter());
        return *this;
    }

    unique_ptr& operator=(nullptr_t) noexcept
    {
        reset();
        return *this;
    }

    typename add_lvalue_reference<element_type>::type
    operator*() const
    {
        _GLIBCXX_DEBUG_ASSERT(get() != pointer());
        return *get();
    }

    pointer operator->() const noexcept
    {
        _GLIBCXX_DEBUG_ASSERT(get() != pointer());
        return get();
    }

    pointer get() const noexcept
    { return std::get<0>(_M_t); }

    deleter_type& get_deleter() noexcept
    { return std::get<1>(_M_t); }

    const deleter_type& get_deleter() const noexcept
    { return std::get<1>(_M_t); }

    explicit operator bool() const noexcept
    { return get() == pointer() ? false : true; }

    pointer release() noexcept
    {
        pointer __p = get();
        std::get<0>(_M_t) = pointer();
        return __p;
    }

    void reset(pointer __p = pointer()) noexcept
    {
        using std::swap;
        swap(std::get<0>(_M_t), __p);
        if (__p != pointer())
            get_deleter()(__p);
    }

    void swap(unique_ptr& __u) noexcept
    {
        using std::swap;
        swap(_M_t, __u._M_t);
    }

    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
};

简单实现

shared_ptr:

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

class counter
{
    int n;
};
template<typename T>
class sharePtr
{
public:
    //初始化的构造函数
    sharePtr(T* p) :m_ptr(p)
    {
        m_count = new counter;
        if (p)
            m_count->n = 1;
    }
    //浅拷贝的构造函数
    sharePtr(sharePtr<T> const& sp)
    {
        m_ptr = sp.m_ptr;
        m_count = sp.m_count;
        (m_count->n)++;
    }
    //析构函数
    ~sharePtr()
    {
        release();
    }
    //拷贝弱指针对象的构造函数
    sharePtr(weak_ptr<T>const& wp)
    {
        m_ptr = wp.m_ptr;
        m_count->n= wp.use_count();
        (m_count->n)++;
    }
    //=重载
    sharePtr<T>& operator=(sharePtr<T> const& sp)
    {
        if (*this != sp)
        {
            release();
            m_ptr = sp.m_ptr;
            m_count = sp.m_count;
            m_count->n++;
        }
        return *this;
    }
    //*重载
    T& operator*()
    {
        return *m_ptr;
    }
    //->重载 4+3=7
    T* operator->()
    {
        return m_ptr;
    }
    
private:
    //智能指针释放控制的对象 
    void release()
    {
        m_count->n--;
        if (m_count->n < 1)
        {
            delete m_ptr;
            m_ptr = nullptr;
            delete m_count;
            m_count = nullptr;
        }
    }
    T* m_ptr;
    counter* m_count;
};

智能指针函数

链接

什么指针需要使用智能指针

哪些不需要

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值