简单实现智能指针--unique_ptr,shared_ptr,weak_ptr

在学习《Effective Modern C++》的过程中学到了智能指针,智能指针对于现代C++编程十分重要,为了加深理解,参考了网上很多智能指针的实现,简单实现了智能指针的基本功能,可能存在问题,欢迎大家指正。

  1. unique_ptr:每个 unique_ptr 指针都独自拥有对其所指堆内存空间的所有权。

成员函数名

功 能

operator*()

获取当前 unique_ptr 指针指向的数据。

operator->()

重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。

operator =()

重载了 = 赋值号,从而可以将 nullptr 或者一个右值 unique_ptr 指针直接赋值给当前同类型的 unique_ptr 指针。

operator []()

重载了 [] 运算符,当 unique_ptr 指针指向一个数组时,可以直接通过 [] 获取指定下标位置处的数据。

get()

获取当前 unique_ptr 指针内部包含的普通指针。

get_deleter()

获取当前 unique_ptr 指针释放堆内存空间所用的规则。

operator bool()

unique_ptr 指针可直接作为 if 语句的判断条件,以判断该指针是否为空,如果为空,则为 false;反之为 true。

release()

释放当前 unique_ptr 指针对所指堆内存的所有权,但该存储空间并不会被销毁。

reset(p)

其中 p 表示一个普通指针,如果 p 为 nullptr,则当前 unique_ptr 也变成空指针;反之,则该函数会释放当前 unique_ptr 指针指向的堆内存(如果有),然后获取 p 所指堆内存的所有权(p 为 nullptr)。

swap(x)

交换当前 unique_ptr 指针和同类型的 x 指针。

  1. shared_ptr:多个指针可以共享同一块内存,底层采用引用计数,当计数为0时,空间被释放

成员方法名

功 能

operator=()

重载赋值号,使得同一类型的 shared_ptr 智能指针可以相互赋值。

operator*()

重载 * 号,获取当前 shared_ptr 智能指针对象指向的数据。

operator->()

重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。

swap()

交换 2 个相同类型 shared_ptr 智能指针的内容。

reset()

当函数没有实参时,该函数会使当前 shared_ptr 所指堆内存的引用计数减 1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的 shared_ptr 对象会获得该存储空间的所有权,并且引用计数的初始值为 1。

get()

获得 shared_ptr 对象内部包含的普通指针。

use_count()

返回同当前 shared_ptr 对象(包括它)指向相同的所有 shared_ptr 对象的数量。

unique()

判断当前 shared_ptr 对象指向的堆内存,是否不再有其它 shared_ptr 对象再指向它。

operator bool()

判断当前 shared_ptr 对象是否为空智能指针,如果是空指针,返回 false;反之,返回 true。

  1. weak_ptr:shared_ptr存在循环引用的问题,通过weak_ptr来解决;除此之外,应用场景还包括缓存和观察者列表

成员方法

功 能

operator=()

重载 = 赋值运算符,是的 weak_ptr 指针可以直接被 weak_ptr 或者 shared_ptr 类型指针赋值。

swap(x)

其中 x 表示一个同类型的 weak_ptr 类型指针,该函数可以互换 2 个同类型 weak_ptr 指针的内容。

reset()

将当前 weak_ptr 指针置为空指针。

use_count()

查看指向和当前 weak_ptr 指针相同的 shared_ptr 指针的数量。

expired()

判断当前 weak_ptr 指针为否过期(指针为空,或者指向的堆内存已经被释放)。

lock()

如果当前 weak_ptr 已经过期,则该函数会返回一个空的 shared_ptr 指针;反之,该函数返回一个和当前 weak_ptr 指向相同的 shared_ptr 指针。

具体实现:

#pragma once
#include <iostream>

namespace Myptr {

    / unique_ptr //
    // 默认删除器
    template <typename T>
    struct PointerDeleter {
        void operator()(const T* ptr) {
            if (ptr) {
                delete ptr;
                ptr = nullptr;
            }
        }
    };

    template<class T, typename Deleter = PointerDeleter<T> >
    class unique_ptr {
    private:
        // 原始指针
        T* ptr;
    public:
        // 构造函数
        explicit unique_ptr() : ptr(nullptr) {}
        explicit unique_ptr(T* _ptr) : ptr(_ptr) {}
        // 移动构造函数
        unique_ptr(unique_ptr&& p) noexcept;
        // 移动赋值函数
        unique_ptr& operator=(unique_ptr&& p) noexcept;
        // 析构函数
        ~unique_ptr() {
            Deleter()(ptr);
            std::cout << "unique ptr destroy!" << std::endl;
        };

        // 重载运算符
        T& operator*() const noexcept { return *ptr; }
        T* operator->() const noexcept { return ptr; }
        explicit operator bool() const noexcept { return ptr != nullptr; };

        // 返回原始指针
        T* get() const noexcept { return ptr; }
        // 返回指针,释放所有权
        T* release() noexcept {
            T* pointer = ptr;
            ptr = nullptr;
            return pointer;
        }
        // 替换被管理的对象
        void reset(T* _ptr = nullptr) noexcept {
            if (ptr != _ptr) {
                Deleter()(ptr);
                ptr = _ptr;
            }
        }
        // 交换被管理的对象
        void swap(unique_ptr& p) noexcept {
            std::swap(ptr, p.ptr);
        }

        // 不允许使用拷贝相关
        unique_ptr(const unique_ptr& p) = delete;
        unique_ptr& operator=(const unique_ptr& p) = delete;
    };


    template <typename T, typename Deleter>
    unique_ptr<T, Deleter>::unique_ptr(unique_ptr&& p) noexcept : ptr(p.ptr) {
        p.ptr = nullptr;
    }

    template <typename T, typename Deleter>
    unique_ptr<T, Deleter>& unique_ptr<T, Deleter>::operator=(unique_ptr&& p) noexcept {
        std::swap(ptr, p.ptr);
        return *this;
    }

    // shared_ptr //
    template<typename T> class weak_ptr; // 声明weak_ptr为模板类
    template<typename T, class Deleter > class shared_ptr; // 声明shared_ptr为模板类
    
    template<class T, class Deleter = PointerDeleter<T> >
    class shared_ptr {
        friend class weak_ptr<T>;
    private:
        T* m_ptr = nullptr;
        size_t* ref_count = nullptr;

    public:
        // 默认构造函数
        explicit shared_ptr(): m_ptr(nullptr), ref_count(new size_t(0)) {}
        explicit shared_ptr(T* ptr): m_ptr(ptr), ref_count(new size_t(1)) {}

        // 拷贝构造函数和拷贝复制函数
        shared_ptr(const shared_ptr& p) {
            m_ptr = p.m_ptr;
            ref_count = p.ref_count;
            if (ref_count != nullptr) {
                (*ref_count)++;
            }
        }
        shared_ptr(const weak_ptr<T>& wp) {
            m_ptr = wp.m_ptr;
            ref_count = wp.ref_count;
            (*ref_count)++;
        }
        shared_ptr& operator=(const shared_ptr& p) {
            if (p.m_ptr == m_ptr) {
                return *this;
            }
            //先处理原有的指针和引用计数
            if (ref_count != nullptr)
            {
                (*ref_count)--;
                if (*ref_count == 0)
                {
                    delete m_ptr;
                    delete ref_count;
                }
            }
            //再处理赋值
            m_ptr = p.m_ptr;
            ref_count = p.ref_count;

            if (ref_count != nullptr)
            {
                (*ref_count)++;
            }
            return *this;
        }

        // 移动构造函数和移动赋值函数
        shared_ptr(shared_ptr&& dying_obj) noexcept : m_ptr(nullptr), ref_count(nullptr) {
            //初始化后交换指针和引用计数, 等于清除了原shared_ptr的内容
            dying_obj.swap(*this);
        }
        shared_ptr& operator=(shared_ptr&& dying_obj) noexcept {
            //my_shared_ptr(std::move(dying_obj))用移动构造函数创建出一个新的shared_ptr(此时dying_obj的内容被清除了)
            //再和this交换指针和引用计数
            //因为this被交换到了当前的临时创建的my_shared_ptr里,this的引用计数-1
            shared_ptr(std::move(dying_obj)).swap(*this);
            //dying_obj.swap(*this);
            return *this;
        }

        // 析构函数
        ~shared_ptr() {
            std::cout << "delete" << std::endl;
            if (ref_count == nullptr)
            {
                return;
            }
            (*ref_count)--;
            if (*ref_count > 0)
            {
                return;
            }

            if (m_ptr != nullptr)
            {
                Deleter()(m_ptr);
            }
            delete ref_count;
            
        }

        // 操作符重载
        T& operator*() const { return *m_ptr; }
        T* operator->() const { return m_ptr; }
        explicit operator bool() { return m_ptr != nullptr; }

        // 工具函数
        void swap(shared_ptr& other) {
            std::swap(m_ptr, other.m_ptr);
            std::swap(ref_count, other.ref_count);
        }

        T* get() const { return m_ptr; }

        size_t use_count() const { 
            return ref_count != nullptr ? *ref_count : 0;
        }

        bool unique() { return *ref_count == 1; }

        void reset(T* ptr = nullptr) {
            if (ptr == nullptr) {
                (*ref_count)--;
                m_ptr = nullptr;
                ref_count = nullptr;
            }
            else {
                shared_ptr<T, Deleter>().swap(*this);

                m_ptr = ptr;
                ref_count = new size_t(1);
            }
        }
    };


    / weak_ptr 
    template<class T>
    class weak_ptr {
        friend class shared_ptr<T>;
    private:
        T* m_ptr;
        size_t* ref_count;

    public:
        weak_ptr() noexcept : m_ptr(nullptr), ref_count(new size_t(0)) {}
        weak_ptr(T* ptr) noexcept : m_ptr(ptr), ref_count(new size_t(1)) {}

        weak_ptr(const weak_ptr& wp): m_ptr(wp.m_ptr), ref_count(wp.ref_count) {}
        weak_ptr(const shared_ptr<T>& sp): m_ptr(sp.m_ptr), ref_count(sp.ref_count) {}

        weak_ptr& operator=(const weak_ptr& wp) {
            if (*this != wp) {
                m_ptr = wp.m_ptr;
                ref_count = wp.ref_count;
            }
            return *this;
        }
        weak_ptr& operator=(const shared_ptr<T>& sp) {
            m_ptr = sp.m_ptr;
            ref_count = sp.ref_count;
            return *this;
        }

        bool expired() const {
            return ref_count == nullptr || *ref_count == 0;
        }

        shared_ptr<T> lock() const {
            if (expired()) {
                return shared_ptr<T>();
            }
            return shared_ptr<T>(*this);
        }

        void reset() {
            m_ptr = nullptr;
            ref_count = nullptr;
        }

        void swap(weak_ptr& wp) {
            std::swap(m_ptr, wp.m_ptr);
            std::swap(ref_count, wp.ref_count);
        }

        size_t use_count() {
            return ref_count != nullptr ? *ref_count : 0;
        }
    };
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值