0

0

C++如何实现一个智能指针_手动实现C++ shared_ptr的引用计数功能

穿越時空

穿越時空

发布时间:2025-12-01 11:50:02

|

892人浏览过

|

来源于php中文网

原创

答案:实现简易 shared_ptr 需定义引用计数控制块,通过构造、拷贝、赋值和析构操作管理资源;1. 使用 int* 动态记录引用计数,多个指针共享同一块内存;2. 拷贝时递增计数,析构或赋值时调用 release 函数递减,为 0 则 delete 资源;3. 支持解引用、get、use_count 等接口;4. 示例验证了构造、作用域析构、赋值等场景下引用计数正确变化;5. 关键点包括独立分配计数、自赋值保护、reset 正确释放旧资源;6. 局限性有非线程安全、无自定义删除器、未优化内存布局,生产环境需改进。

c++如何实现一个智能指针_手动实现c++ shared_ptr的引用计数功能

实现一个简易的 shared_ptr 智能指针,核心是模拟引用计数机制,确保多个指针共享同一块内存时,只有最后一个指针释放时才真正 delete 资源。下面是一个手动实现的基本版本,包含构造、拷贝、赋值和析构等关键操作。

1. 定义引用计数控制块

我们需要一个额外的结构体来管理原始指针和引用计数,这个结构体被所有共享该对象的智能指针共用。

template 
class SharedPtr {
private:
    T* ptr;                    // 指向实际数据的指针
    int* ref_count;            // 指向引用计数的指针
void release() {
    if (ref_count && --(*ref_count) == 0) {
        delete ptr;
        delete ref_count;
        ptr = nullptr;
        ref_count = nullptr;
    }
}

public: // 构造函数:接管原始指针 explicit SharedPtr(T* p = nullptr) : ptr(p), ref_count(nullptr) { if (ptr) { ref_count = new int(1); } }

// 拷贝构造函数
SharedPtr(const SharedPtr& other) : ptr(other.ptr), ref_count(other.ref_count) {
    if (ref_count) {
        ++(*ref_count);
    }
}

// 拷贝赋值运算符
SharedPtr& operator=(const SharedPtr& other) {
    if (this != &other) {
        release();  // 释放当前资源
        ptr = other.ptr;
        ref_count = other.ref_count;
        if (ref_count) {
            ++(*ref_count);
        }
    }
    return *this;
}

// 析构函数
~SharedPtr() {
    release();
}

// 解引用
T& operator*() const { return *ptr; }
T* operator->() const { return ptr; }

// 获取原始指针
T* get() const { return ptr; }

// 获取引用计数(调试用)
int use_count() const { return ref_count ? *ref_count : 0; }

// 判断是否唯一拥有
bool unique() const { return use_count() == 1; }

// 重置指针
void reset(T* p = nullptr) {
    release();
    ptr = p;
    if (ptr) {
        ref_count = new int(1);
    } else {
        ref_count = nullptr;
    }
}

};

2. 使用示例

测试我们实现的 SharedPtr 是否正确管理引用计数。

立即学习C++免费学习笔记(深入)”;

PageOn
PageOn

AI驱动的PPT演示文稿创作工具

下载
#include 

struct MyClass { int value; MyClass(int v) : value(v) { std::cout << "MyClass(" << v << ") created\n"; } ~MyClass() { std::cout << "MyClass destroyed\n"; } };

int main() { SharedPtr sp1(new MyClass(42)); std::cout << "use count: " << sp1.use_count() << "\n";

{
    SharedPtrzuojiankuohaophpcnMyClassyoujiankuohaophpcn sp2 = sp1;
    std::cout zuojiankuohaophpcnzuojiankuohaophpcn "use count after copy: " zuojiankuohaophpcnzuojiankuohaophpcn sp1.use_count() zuojiankuohaophpcnzuojiankuohaophpcn "\n";
} // sp2 析构,引用计数减一

std::cout zuojiankuohaophpcnzuojiankuohaophpcn "use count after sp2 destroyed: " zuojiankuohaophpcnzuojiankuohaophpcn sp1.use_count() zuojiankuohaophpcnzuojiankuohaophpcn "\n";

SharedPtrzuojiankuohaophpcnMyClassyoujiankuohaophpcn sp3;
sp3 = sp1; // 赋值测试
std::cout zuojiankuohaophpcnzuojiankuohaophpcn "use count after assignment: " zuojiankuohaophpcnzuojiankuohaophpcn sp1.use_count() zuojiankuohaophpcnzuojiankuohaophpcn "\n";

return 0;

}

3. 关键点说明

这个简易实现展示了 shared_ptr 的核心思想:

  • 引用计数独立分配:使用 int* 动态分配计数,确保多个实例共享同一个计数值。
  • release 函数:在析构和赋值时调用,负责递减计数并清理资源。
  • 自赋值保护:赋值前检查 this != &other,避免错误释放。
  • reset 方法:允许智能指针切换到新对象,并正确处理旧资源。

4. 局限性与改进方向

此实现是教学性质的简化版,生产环境的 shared_ptr 还需考虑:

  • 线程安全:多线程下引用计数应使用原子操作(如 std::atomic)。
  • 支持自定义删除器(deleter)。
  • weak_ptr 配合避免循环引用。
  • 性能优化:比如控制块与对象一起分配,减少内存碎片。

基本上就这些。理解引用计数的生命周期管理,是掌握智能指针的关键。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

755

2023.08.22

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

197

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

189

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

540

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1027

2023.10.19

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号