• C++ 简单实现shared_ptr


    共享指针

    管理指针的存储,提供有限的垃圾回收工具,并可能与其他对象共享该管理。

    shared_ptr类型的对象都能够获得指针的所有权并共享该所有权:一旦它们获得所有权,当最后一个所有者释放该所有权时,指针的所有者组就负责删除该所有者。

    shared_ptr对象在自身被销毁后,或者一旦其值因赋值操作或显式调用 shared_ptr::reset 而发生更改,就会释放其共同拥有的对象的所有权。一旦通过指针共享所有权的所有shared_ptr对象都释放了此所有权,则将删除托管对象(通常通过调用 ::delete,但在构造时可能会指定不同的删除程序)。

    shared_ptr对象只能通过复制其值来共享所有权:如果从同一个(非shared_ptr)指针构造(或创建)两个shared_ptr,则它们都将拥有该指针而不共享它,当其中一个对象释放它(删除其托管对象)并使另一个指向无效位置时,会导致潜在的访问问题。

    此外,shared_ptr对象可以通过指针共享所有权,同时指向另一个对象。此功能称为别名,通常用于指向成员对象,同时拥有它们所属的对象。因此,shared_ptr可能与两个指针相关:

    • 存储的指针,它是它所指向的指针,也是它使用运算符* 取消引用的指针。
    • 拥有的指针(可能是共享的),这是所有权组负责在某个时刻删除的指针,并且它被视为一种用途。

    通常,存储的指针和拥有的指针引用同一对象,但别名shared_ptr对象(使用别名构造函数及其副本构造的对象)可能引用不同的对象。

    不拥有任何指针的shared_ptr称为空shared_ptr。不指向任何对象的shared_ptr称为 null shared_ptr,不应取消引用。请注意,空shared_ptr不一定是 null shared_ptr,null shared_ptr不一定是空shared_ptr。

    shared_ptr对象通过运算符 * 和 -> 提供对它们所指向的对象的访问,从而复制有限的指针功能。出于安全原因,它们不支持指针算术。

    相关类weak_ptr能够与shared_ptr对象共享指针,而无需拥有它们。

    成员函数

    	(构造函数)构造shared_ptr(公共成员函数)
    	(析构函数)销毁shared_ptr(公共成员函数)
    	operator=	shared_ptr赋值(公共成员函数)
    	swap	交换内容(公共成员函数)
    	reset	重置指针(公共成员函数)
    	get	获取指针(公共成员函数)
    	operator*	取消引用对象(公共成员函数)
    	operator->	取消引用对象成员(公共成员函数)
    	operator[]  (C++17)提供到被存储数组的带下标访问(公开成员函数)
    	use_count	返回计数(公共成员函数)
    	unique(C++20前)	检查是否唯一(公共成员函数)
    	operator bool	检查是否不为空(公共成员函数)
    	owner_before	基于所有者的共享指针排序(公共成员函数模板)
    
    非成员函数
    	swap	交换shared_ptr对象的内容(函数模板)
    	relational operators	关系运算符 ==, !=, <, <=, >, >= (函数模板 )
    	ostream operator<<	将存储的指针的值输出到输出流(函数模板)
    
    具体功能:
    	make_shared,make_shared_for_overwrite(C++20)	创建管理一个新对象的共享指针(函数模板)
    	allocate_shared,allocate_shared_for_overwrite(C++20)	创建管理一个用分配器分配的新对象的共享指针(函数模板)
    	static_pointer_cast,dynamic_pointer_cast,const_pointer_cast,reinterpret_pointer_cast    (C++17)应用 static_cast、dynamic_cast、const_cast 或 reinterpret_cast 到被存储指针(函数模板)
    	get_deleter	返回指定类型中的删除器,若其拥有(函数模板)
    

    cpp

    #include <utility>
    #include <cstddef>
    
    class ref_count
    {
    public:
        int use_count() const noexcept { return count_; }
        void inc_ref() noexcept { ++count_; }
        int dec_ref() noexcept { return --count_; }
    
    private:
        int count_{1};
    };
    
    template <typename T>
    class Shared_ptr
    {
    public:
        constexpr Shared_ptr() noexcept = default;
        constexpr Shared_ptr(nullptr_t) noexcept : Shared_ptr() {}
        explicit Shared_ptr(T *ptr) : ptr_{ptr}
        {
            if (ptr_ != nullptr)
            {
                rep_ = new ref_count{};
            }
        }
        Shared_ptr(const Shared_ptr &rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_}
        {
            if (ptr_ != nullptr)
            {
                rep_->inc_ref();
            }
        }
        Shared_ptr(Shared_ptr &&rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_}
        {
            rhs.ptr_ = nullptr;
            rhs.rep_ = nullptr;
        }
        ~Shared_ptr() noexcept
        {
            if (rep_ != nullptr && rep_->dec_ref() == 0)
            {
                delete ptr_;
                delete rep_;
            }
        }
    
        Shared_ptr &operator=(const Shared_ptr &rhs)
        {
            Shared_ptr{rhs}.swap(*this);
            return *this;
        }
        Shared_ptr &operator=(Shared_ptr &&rhs)
        {
            Shared_ptr{std::move(rhs)}.swap(*this);
            return *this;
        }
        void reset() noexcept
        {
            Shared_ptr{}.swap(*this);
        }
        void reset(nullptr_t) noexcept
        {
            reset();
        }
        void reset(T *ptr)
        {
            Shared_ptr{ptr}.swap(*this);
        }
    
        void swap(Shared_ptr &rhs) noexcept
        {
            std::swap(ptr_, rhs.ptr_);
            std::swap(rep_, rhs.rep_);
        }
        T *get() const noexcept
        {
            return ptr_;
        }
    
        long use_count() const noexcept
        {
            return rep_ == nullptr ? 0 : rep_->use_count();
        }
        bool unique() const noexcept
        {
            return rep_->use_count() == 1;
        }
    
        T &operator*() const noexcept
        {
            return *ptr_;
        }
        T &operator->() const noexcept
        {
            return ptr_;
        }
    
        explicit operator bool() const noexcept
        {
            return static_cast<bool>(ptr_);
        }
    
    private:
        T *ptr_{nullptr};
        ref_count *rep_{nullptr};
    };
    
    template <typename T, typename... Args>
    auto make_Shared(Args &&...args)
    {
        return Shared_ptr<T>{new T(std::forward(args)...)};
    }
    
  • 相关阅读:
    【C# 调用 Go 语言】
    Go语言多线程 (转)
    CodeSoft 2019 企业版打标签
    (转)FFT求频谱图和功率谱密度图
    使用NI-DAQmx进行振动数据采集
    CentOS7 安装配置笔记
    .net 调用 nsfwjs 进行视频鉴别
    Electron.Net + Linux + Blazor 初尝备忘录
    关于feign调用的时候,动态传url ,以及自定义head
    go使用excelize导出xls
  • 原文地址:https://www.cnblogs.com/chengmf/p/15978705.html
Copyright © 2020-2023  润新知