智能指针的实现原理是什么

智能指针的实现原理主要基于 RAII(Resource Acquisition Is Initialization,资源获取即初始化) 技术,通过对象的生命周期来管理动态分配的内存。其核心思想是:将资源的获取与对象的构造绑定,资源的释放与对象的析构绑定。这样,当智能指针对象离开作用域或被销毁时,会自动释放其管理的资源,从而避免内存泄漏。

1. std::unique_ptr(独占所有权)

核心原理:

unique_ptr 通过独占所有权机制确保同一时间只有一个指针拥有资源。它内部封装了一个原始指针,并通过禁用拷贝构造函数和拷贝赋值运算符(只允许移动语义)来实现独占性。

关键实现:

使用 delete 关键字禁用拷贝构造函数和拷贝赋值运算符。

允许通过移动构造函数和移动赋值运算符转移所有权。

在析构函数中调用 delete(或自定义的删除器)释放资源。

template <typename T>
class unique_ptr {
private:
    T* ptr;  // 内部原始指针
public:
    explicit unique_ptr(T* p) : ptr(p) {}
    ~unique_ptr() { delete ptr; }  // 析构时自动释放资源

    // 禁用拷贝
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;

    // 允许移动
    unique_ptr(unique_ptr&& other) noexcept : ptr(other.ptr) {
        other.ptr = nullptr;  // 移动后原指针置空
    }
    unique_ptr& operator=(unique_ptr&& other) noexcept {
        if (this != &other) {
            delete ptr;        // 释放当前资源
            ptr = other.ptr;
            other.ptr = nullptr;
        }
        return *this;
    }

    T* get() const { return ptr; }
    T& operator*() const { return *ptr; }
    // 其他成员函数...
};

2. std::shared_ptr(共享所有权)

核心原理:

shared_ptr 通过 引用计数(Reference Counting) 实现共享所有权。多个 shared_ptr 可以指向同一对象,引用计数记录当前有多少个 shared_ptr 指向该对象。当引用计数降为 0 时,对象被销毁。

关键实现:

内部维护一个 控制块(Control Block),包含:

指向资源的指针。

引用计数(use_count):记录当前有多少个 shared_ptr 指向资源。

弱引用计数(weak_count):记录 weak_ptr 的引用次数。

每次拷贝构造或赋值时,引用计数加 1;每次析构时,引用计数减 1。

当引用计数为 0 时,调用 delete(或自定义删除器)释放资源。

控制块本身是线程安全的(通过原子操作保证引用计数的修改是原子的)。

template <typename T>
class shared_ptr {
private:
    T* ptr;              // 指向资源的指针
    ControlBlock* cb;    // 控制块指针
public:
    explicit shared_ptr(T* p) : ptr(p), cb(new ControlBlock) {
        cb->use_count = 1;
    }

    // 拷贝构造函数:引用计数 +1
    shared_ptr(const shared_ptr& other) : ptr(other.ptr), cb(other.cb) {
        cb->use_count++;
    }

    // 析构函数:引用计数 -1,若为 0 则释放资源
    ~shared_ptr() {
        if (--cb->use_count == 0) {
            delete ptr;
            if (cb->weak_count == 0) {
                delete cb;
            }
        }
    }

    // 其他成员函数...
};

3. std::weak_ptr(弱引用)

核心原理:

weak_ptr 是为了解决 shared_ptr 的 循环引用问题 而设计的。它指向 shared_ptr 管理的资源,但不会增加引用计数。通过 weak_ptr 可以安全地观察资源是否存在,而不会影响其生命周期。

关键实现:

内部同样维护一个指向控制块的指针,但不操作引用计数(use_count),只操作弱引用计数(weak_count)。

需要通过 lock() 方法获取一个临时的 shared_ptr 来访问资源。如果资源已被释放,lock() 返回空指针。

template <typename T>
class weak_ptr {
private:
    T* ptr;
    ControlBlock* cb;
public:
    weak_ptr(const shared_ptr<T>& sp) : ptr(sp.ptr), cb(sp.cb) {
        cb->weak_count++;
    }

    ~weak_ptr() {
        cb->weak_count--;
        if (cb->use_count == 0 && cb->weak_count == 0) {
            delete cb;  // 释放控制块
        }
    }

    shared_ptr<T> lock() const {
        if (cb->use_count > 0) {
            return shared_ptr<T>(*this);
        } else {
            return nullptr;
        }
    }
};

4. 循环引用问题与 weak_ptr 的解决

问题场景:

两个对象互相持有对方的 shared_ptr,导致引用计数永远无法降为 0,资源无法释放。

解决方案:

将其中一个 shared_ptr 替换为 weak_ptr。weak_ptr 不会增加引用计数,因此不会阻止资源的释放。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值