智能指针。多个指针共享同一资源,最后一个释放资源”
#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;}// 其他方法保持不变...
};
三种方案对比
方案 | 互斥锁类型 | 优点 | 缺点 |
---|---|---|---|
静态互斥锁 | 类级别(所有实例共享) | 实现简单,开销小 | 多实例跨资源操作时可能形成瓶颈 |
独立互斥锁 | 每个资源关联一个锁 | 精细化控制,减少锁竞争 | 内存开销增加(每个资源多一个锁) |
原子操作 | 无锁方案 | 无锁开销,性能最优 | 实现复杂,需处理内存序问题 |
在实际应用中,推荐优先使用方案三(原子操作),因为智能指针的引用计数本质是一个整数增减操作,原子操作可以高效且无锁地完成这一任务,避免了锁带来的上下文切换开销和潜在的死锁风险。