C++智能指针

2022-02-11  本文已影响0人  LEO_青蛙

智能指针其实本质是一个模板类,一般使用是用的这个类的对象,而不是指针
智能指针体现在内存释放问题,用智能指针管理new的对象,不需要手动delete

1、唯一指针std::unique_ptr<T>

独占资源所有权的指针。
(1)使用 std::unique_ptr 自动管理内存

{
    std::unique_ptr<int> uptr = std::make_unique<int>(200);
    //...
    // 离开 uptr 的作用域的时候自动释放内存
}

(2)std::unique_ptr 是 move-only 的

{
    std::unique_ptr<int> uptr = std::make_unique<int>(200);
    std::unique_ptr<int> uptr1 = uptr;  // 编译错误,std::unique_ptr<T> 是 move-only 的

    std::unique_ptr<int> uptr2 = std::move(uptr);
    assert(uptr == nullptr);
}

2、共享指针std::shared_ptr<T>

共享资源所有权的指针。
shared_ptr 需要维护的信息有两部分:
(1)指向共享资源的指针
(2)引用计数等共享资源的控制信息——实现上是维护一个指向控制信息的指针。
简单实现共享指针

template<typename T>
class shared_ptr
{
private:
    T* _ptr;
    int* _count;//共享引用计数,必须使用指针
public:
    //构造函数
    shared_ptr(T* ptr = nullptr) : _ptr(ptr)
    {
        if (_ptr)
        {
            _count = new int(1);
        }
        else
        {
            _count = new int(0);
        }
    }

    //拷贝构造
    shared_ptr(const shared_ptr& ptr)
    {
        if (this != &ptr)
        {
            this->_ptr = ptr._ptr;
            this->_count = ptr._count;
            //引用计数+1
            (*this->_count)++;
        }
    }

    //重载operator=
    shared_ptr& operator=(const shared_ptr& ptr)
    {
        if (this->_ptr == ptr._ptr)
        {
            return *this;
        }
        if (this->_ptr)
        {
            (*this->_count)--;
            if (*this->_count == 0)
            {
                delete this->_ptr;
                delete this->_count;
            }
        }
        this->_ptr = ptr._ptr;
        this->_count = ptr._count;
        (*this->_count)++;
        return *this;
    }

    //重载operator*
    T& operator*()
    {
        if (this->_ptr)
        {
            return *(this->_ptr);
        }
    }

    //重载operator->
    T* operator->()
    {
        if (this->_ptr)
        {
            return this->_ptr;
        }
    }

    //析构函数
    ~shared_ptr()
    {
        (*this->_count)--;
        if (*this->_count == 0)
        {
            delete this->_ptr;
            delete this->_count;
        }
    }

    //引用计数
    int use_count()
    {
        return *this->_count;
    }
};

3、弱引用指针std::weak_ptr<T>

共享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。
注意事项:
(1)弱引用指针,不会累计引用计数
(2)weak_ptr只能通过shared_ptr或者weak_ptr来构造
(3)主要应用场景:为了解决shared_ptr循环引用,导致内存无法释放问题
(4)通过成员函数lock获取shared_ptr对象,然后再访问数据
shared_ptr循环引用:

class A
{
public:
    A() {};
    ~A() {};
    std::shared_ptr<B> b;
private:

};

class B
{
public:
    B() {};
    ~B() {};
    std::shared_ptr<A> a;
private:

};

int main()
{
    //循环引用,无法析构
    std::shared_ptr<A> ptr_a = std::make_shared<A>();
    std::shared_ptr<B> ptr_b = std::make_shared<B>();
    ptr_a->b = ptr_b;
    ptr_b->a = ptr_a;
    return 1;
}
上一篇下一篇

猜你喜欢

热点阅读