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

智能指针。多个指针共享同一资源,最后一个释放资源”

#include <iostream>using namespace std;// 测试结构体:包含一个整数成员
struct Stu {int score;
};// 智能指针类模板,管理类型T的资源
template <typename T>
class smart_ptr {
private:T* p;          // 指向管理的原始资源(堆内存)int* count;    // 引用计数,所有共享同一资源的智能指针指向同一个count// 私有构造函数:禁止直接用裸指针初始化,强制通过工厂方法创建smart_ptr(T* ptr) : p(ptr), count(new int(1)) {}  // 初始化计数为1public:// 静态工厂方法:创建智能指针,确保资源来自堆内存(new T(val))static smart_ptr make_smart(const T& val) {return smart_ptr(new T(val));  // 动态分配T类型对象并初始化}// 拷贝构造函数:共享资源,引用计数+1smart_ptr(const smart_ptr& other) : p(other.p), count(other.count) {(*count)++;  // 计数递增,记录新的引用}// 析构函数:释放资源(当引用计数为0时)~smart_ptr() {if (count) {  // 检查count是否为nullptr(避免空指针解引用)                            (*count)--;  // 计数递减if (*count == 0) {  // 计数为0时,释放资源delete p;      // 释放原始资源(T类型对象)delete count;   // 释放引用计数内存}}}// 赋值运算符:处理资源转移,确保正确释放旧资源并共享新资源smart_ptr& operator=(const smart_ptr& other) {if (this != &other) {  // 避免自赋值// 释放当前管理的资源(若计数为0,删除内存)if (count) {(*count)--;if (*count == 0) {delete p;delete count;}}// 接管新资源,计数+1p = other.p;count = other.count;if (count) (*count)++;  // 确保count有效时递增(避免空指针解引用)}return *this;  // 返回当前对象,支持链式赋值}// 解引用运算符:访问原始资源(T类型对象的引用)T& operator*() {return *p;  // 解引用原始指针,返回对象引用}// 箭头运算符:访问原始资源的成员(模拟指针行为)T* operator->() {return p;  // 返回原始指针,支持成员访问(如s->score)}// 获取引用计数(仅用于调试,查看当前有多少智能指针共享资源)int use_count() const {return count ? *count : 0;  // 若count为nullptr(资源已释放),返回0}
};int main() {// 示例1:管理int类型资源smart_ptr<int> p1 = smart_ptr<int>::make_smart(100);  // 创建p1,计数1smart_ptr<int> p3 = p1;                               // 拷贝p1→p3,计数2cout << "p1 count: " << p1.use_count() << endl;       // 输出2(验证计数)// 示例2:管理Stu结构体资源smart_ptr<Stu> s = smart_ptr<Stu>::make_smart({120});  // 创建s,计数1cout << "Score: " << s->score << endl;                // 输出120(通过->访问成员)return 0;  // 离开作用域时,所有智能指针析构:// p3先析构(计数1),p1再析构(计数0,释放int资源)// s析构(计数0,释放Stu资源),无内存泄漏
}

添加了多线程安全的互斥锁机制,并提供了两种确保互斥的方案:

方案一:使用静态互斥锁(类级别)

cpp

运行

#include <iostream>
#include <mutex>using namespace std;template <typename T>
class smart_ptr {
private:T* p;int* count;static mutex mtx;  // 静态互斥锁,所有实例共享smart_ptr(T* ptr) : p(ptr), count(new int(1)) {}public:static smart_ptr make_smart(const T& val) {return smart_ptr(new T(val));}// 拷贝构造函数:加锁保护引用计数操作smart_ptr(const smart_ptr& other) {lock_guard<mutex> lock(mtx);  // 自动加锁解锁p = other.p;count = other.count;(*count)++;}// 析构函数:加锁保护引用计数操作~smart_ptr() {lock_guard<mutex> lock(mtx);if (count) {(*count)--;if (*count == 0) {delete p;delete count;}}}// 赋值运算符:加锁保护引用计数操作smart_ptr& operator=(const smart_ptr& other) {if (this != &other) {lock_guard<mutex> lock(mtx);  // 自动加锁解锁// 释放当前资源if (count) {(*count)--;if (*count == 0) {delete p;delete count;}}// 接管新资源p = other.p;count = other.count;if (count) (*count)++;}return *this;}// 其他方法保持不变...
};// 静态成员初始化
template <typename T>
mutex smart_ptr<T>::mtx;

方案二:每个引用计数关联独立互斥锁(非静态)

cpp

运行

template <typename T>
class smart_ptr {
private:T* p;int* count;mutex* mtx;  // 每个资源关联一个独立的互斥锁smart_ptr(T* ptr) : p(ptr), count(new int(1)), mtx(new mutex) {}public:// 拷贝构造函数:复制指针并增加引用计数smart_ptr(const smart_ptr& other) : p(other.p), count(other.count), mtx(other.mtx) {lock_guard<mutex> lock(*mtx);  // 锁定原对象的互斥锁(*count)++;}// 析构函数:减少引用计数,必要时释放资源~smart_ptr() {lock_guard<mutex> lock(*mtx);  // 锁定当前对象的互斥锁(*count)--;if (*count == 0) {delete p;delete count;delete mtx;  // 释放互斥锁}}// 赋值运算符:处理资源转移smart_ptr& operator=(const smart_ptr& other) {if (this != &other) {// 先锁定两个互斥锁,防止死锁lock(*mtx, *other.mtx);lock_guard<mutex> lock1(*mtx, adopt_lock);lock_guard<mutex> lock2(*other.mtx, adopt_lock);// 释放当前资源(*count)--;if (*count == 0) {delete p;delete count;delete mtx;}// 接管新资源p = other.p;count = other.count;mtx = other.mtx;(*count)++;}return *this;}// 其他方法保持不变...
};

方案三:使用原子操作(无锁方案)

cpp

运行

#include <atomic>template <typename T>
class smart_ptr {
private:T* p;std::atomic<int>* count;  // 使用原子计数器smart_ptr(T* ptr) : p(ptr), count(new std::atomic<int>(1)) {}public:// 拷贝构造函数:原子操作增加引用计数smart_ptr(const smart_ptr& other) : p(other.p), count(other.count) {count->fetch_add(1, std::memory_order_relaxed);}// 析构函数:原子操作减少引用计数~smart_ptr() {if (count->fetch_sub(1, std::memory_order_acq_rel) == 1) {delete p;delete count;}}// 赋值运算符:原子操作处理引用计数smart_ptr& operator=(const smart_ptr& other) {if (this != &other) {// 增加新引用计数(防止原对象被释放)other.count->fetch_add(1, std::memory_order_relaxed);// 减少旧引用计数,必要时释放if (count->fetch_sub(1, std::memory_order_acq_rel) == 1) {delete p;delete count;}// 更新指针和计数器p = other.p;count = other.count;}return *this;}// 其他方法保持不变...
};

三种方案对比

方案互斥锁类型优点缺点
静态互斥锁类级别(所有实例共享)实现简单,开销小多实例跨资源操作时可能形成瓶颈
独立互斥锁每个资源关联一个锁精细化控制,减少锁竞争内存开销增加(每个资源多一个锁)
原子操作无锁方案无锁开销,性能最优实现复杂,需处理内存序问题

在实际应用中,推荐优先使用方案三(原子操作),因为智能指针的引用计数本质是一个整数增减操作,原子操作可以高效且无锁地完成这一任务,避免了锁带来的上下文切换开销和潜在的死锁风险。

http://www.xdnf.cn/news/10913.html

相关文章:

  • ARM架构推理Stable Diffusiond
  • 使用seaborn/matplotlib定制好看的confusion matrix
  • Spring Boot 的自动装配
  • C++学者给您讲数学之——数列
  • 星野录(博客系统)测试报告
  • 在 Ubuntu 系统上使用 Python 的 Matplotlib 库时遇到的字体缺失问题
  • 武器的攻击判定
  • 多层 PCB 板抄板实操解析:技巧到实操步骤
  • Spring Boot 自动配置原理:从入门到精通
  • MySQL强化关键_019_索引优化
  • ​库存周转战争:用数据驱动取代经验主义,让资金活起来​
  • 7.5- Loading a pretrained LLM
  • 【25.06】FISCOBCOS安装caliper+报错解决
  • Python 元组方法全集详解
  • 登录vmware vcenter报vSphere Client service has stopped working错误
  • H.264编码
  • Axure设计案例:滑动拼图解锁
  • 深度学习介绍
  • web程序设计期末复习-简答题
  • 操作系统 第 39 章 插叙:文件和目录
  • 如何实现RAG与MCP集成
  • 多任务学习(Multi-Task Learning, MTL)
  • unity UI Rect Transform“高”性能写法
  • 52. N 皇后 II【 力扣(LeetCode) 】
  • 网络攻防技术九:网络监听技术
  • Dispatch PDI V2.04 发布预告
  • Ros2 简单构建项目的流程以及涉及的文件作用
  • WAF绕过,网络层面后门分析,Windows/linux/数据库提权实验
  • 【时时三省】(C语言基础)数组作为函数参数
  • 解决Vditor加载Markdown网页很慢的问题(Vite+JS+Vditor)