当前位置: 首页 > news >正文

手写智能指针shared_ptr

手写智能指针shared_ptr


本文尝试手写shared_ptr,此外如果使用memory库中的make_shared相对于shared_ptr有以下好处:

  1. make_shared会在一次内存分配中同时分配对象本体和引用计数
  2. 减少安全异常,两次操作变一个
  3. 高效的引用计数管理,一个内存块中存储对象和引用计数,指针访问时减少额外的缓存访问
  4. 代码简洁不用new
#include<iostream>
#include<memory>



template<typename T>
class ShareCount{
private:
    T* ptr;//指针管理的对象
    int count;//引用计数
    //禁止拷贝构造函数和赋值
    ShareCount(const ShareCount&)=delete;
    ShareCount& operator=(const ShareCount&)=delete;
public:
    //构造函数
    ShareCount(T *p):ptr(p),count(1){};
    //析构
    ~ShareCount(){delete ptr;};
    
    //增加引用计数
    void increment(){
        count++;
        };
    //减少引用计数
    void decrement(){
        //如果计数为0则删除对象
        if(--count==0){
            delete this;
        }
    };

    //返回指针管理的对象
    T* get() const{
        return ptr;
    }
};


template<typename T>
class shared_ptr{
private:
    T* ptr;//指向指针管理的对象
    ShareCount<T> *countPtr;//管理智能指针引用计数器类对象
public:
    //构造函数
    shared_ptr(T* p = nullptr):ptr(p){
       //调用构造
        if(p){
            countPtr=new ShareCount<T>(p);
        }else{
            countPtr=nullptr;
        }
    }
    //拷贝构造 不新开辟空间 只添加计数
    shared_ptr(const shared_ptr& other):ptr(other.ptr),countPtr(other.countPtr){
        //如果智能指针引用对象存在则计数器加1
        if(countPtr){
            countPtr->increment();
        }
    }
    //移动构造 std::move等转为右值引用时调用,右值&&及临时存在的对象
    //移动构造参数不加const,并删除原来的资源
    shared_ptr(shared_ptr&& other):ptr(other.ptr),countPtr(other.countPtr){
        other.ptr=nullptr;
        other.countPtr=nullptr;
    }
    //析构函数
    ~shared_ptr(){
        if(countPtr){
            countPtr->decrement();
        }
    }
    //重写shared_ptr的-> 返回的是T* 指向指针管理的对象
    T* operator->() const {
        return ptr;
    }
    //解引用返回的是T* 指针的解引用
    T& operator*() const{
        return *ptr;
    }
    //reset 
    void reset(T* p = nullptr){
        //如果两个指针不相同,指针改变
        if(p!=ptr){
            //计数器不为空,且指针改变(减少一个),计数器应该减去1
            if(countPtr){
                countPtr->decrement();
            }
        }
        //相同或者不同都指向新的空间,只是不同会导致计数器减一
        //如果为空则为nullptr
        ptr=p;
        if(p){
            //如果p不为空,创建新的计数器
            countPtr=new ShareCount<T>(p);
        }else{
            countPtr=nullptr;
        }
    }

    //公共方法get返回指针
    T* get() const{
        return ptr;
    }

};
struct data{
    int mydata;
    data(int d){
        mydata=d;
    }
};
int main(){
    shared_ptr<int> ptr1(new int(10));
    //调用拷贝构造,ptr和countPtr都是同一个,只是countPtr increment调用了count+1

    shared_ptr<int> ptr2=ptr1;

    std::cout<<"ptr1:"<<(*ptr1)<<std::endl;
    std::cout<<"ptr2:"<<(*ptr2)<<std::endl;

    ptr1.reset();

    std::cout<<"ptr2:"<<(*ptr2)<<std::endl;
    
    shared_ptr<int> ptr3=std::move(ptr2);
    // ptr2为空 以下代码Segmentation fault
    // cout<<"ptr2:"<<(*ptr2)<<endl;

    std::cout<<"ptr3:"<<(*(ptr3.get()))<<std::endl;

    //memory中std::shared_ptr也有类似效果
    std::shared_ptr<int> p1(new int(10));
    std::cout<<"std::p1:"<<(*p1)<<std::endl;
    //或者使用memory中make_shared就不用new了
    // 1.make_shared会在一次内存分配中同时分配对象本体和引用计数
    // 2.减少安全异常,两次操作变一个
    // 3.高效的引用计数管理,一个内存块中存储对象和引用计数,减少额外指针的访问
    // 4.代码简洁不用new
    std::shared_ptr<int> p2=std::make_shared<int>(10);
    std::cout<<"std::p2:"<<(*p2)<<std::endl;
    return 0;
}


文章转载自:

http://hg7Gn0W2.kbhrq.cn
http://IMZysaO8.kbhrq.cn
http://q8MPeOf9.kbhrq.cn
http://gVQ5EYzG.kbhrq.cn
http://022Rpf34.kbhrq.cn
http://svcZk2CR.kbhrq.cn
http://emhAhKoB.kbhrq.cn
http://4yu93s57.kbhrq.cn
http://MampSEYi.kbhrq.cn
http://RgkpROmw.kbhrq.cn
http://5jcCGIJz.kbhrq.cn
http://wtRBxvX7.kbhrq.cn
http://74SF5wTJ.kbhrq.cn
http://QsKSycPK.kbhrq.cn
http://p1ezZNgA.kbhrq.cn
http://y9bMROMf.kbhrq.cn
http://zTZepLjC.kbhrq.cn
http://3jbJ9tpb.kbhrq.cn
http://HrNL1H9m.kbhrq.cn
http://c8h7k06F.kbhrq.cn
http://rejG9dCw.kbhrq.cn
http://Ss0VgexR.kbhrq.cn
http://q2Z16kc8.kbhrq.cn
http://3rXRbXkN.kbhrq.cn
http://Mj40JNLs.kbhrq.cn
http://vcAj6UsT.kbhrq.cn
http://QGihcf6p.kbhrq.cn
http://G7FdJ5U2.kbhrq.cn
http://zmeAcm6Q.kbhrq.cn
http://FdiQgjnV.kbhrq.cn
http://www.dtcms.com/a/66165.html

相关文章:

  • 【软考网工-实践篇】DHCP 动态主机配置协议
  • springboot436-基于SpringBoot的汽车票网上预订系统(源码+数据库+纯前后端分离+部署讲解等)
  • Windsurf初体验
  • CUDA编程之OpenCV与CUDA结合使用
  • 人工智能】数据挖掘与应用题库(401-500)
  • c++介绍智能指针 十二(1)
  • python画图文字显示不全
  • win32汇编环境,网络编程入门之四
  • 奥威BI多数据源融合分析
  • (十一) 人工智能 - Python 教程 - Python元组
  • 【机器学习】主成分分析法求数据前n个主成分
  • deepseek使用记录21——脑图记录
  • 树莓科技集团董事长:第五代产业园运营模式的深度剖析与展望​
  • STM32上实现简化版的AUTOSAR DEM模块
  • LLM增强语义嵌入的模型算法综述
  • Ollama有安全漏洞! 国家网络安全通报中心紧急通报
  • Node.js 与 MongoDB:高效的企业级应用开发
  • Linux监控网络状态
  • dns域名双栈解析
  • XML语法
  • 双因素拆解法 - 分析比例型指标的因子贡献度
  • 文件系统 linux ─── 第19课
  • 2025-03-13 学习记录--C/C++-PTA 练习2-17 生成3的乘方表
  • 【 Linux 系统中 /etc/resolv.conf 文件的 DNS 配置】
  • 《海南建筑安全员C证》与其他地区有什么区别?
  • 计算机视觉算法实战——驾驶员玩手机检测(主页有源码)
  • AlphaDrive:通过强化学习和推理释放自动驾驶中 VLM 的力量
  • Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR
  • TypeScript泛型深度剖析:对比JavaScript的灵活与严谨
  • Linux第二次练习