You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何shared_ptr赋值后未将原始指针置空?详解operator=逻辑

问题拆解与解答

1. 为何a2 = a3;后A(2)析构,但原始指针a_raw仍非nullptr且val_为0?

shared_ptr的核心是管理对象的所有权,而非直接控制你手动持有的原始指针。执行a2 = a3;时:

  • a2原本持有A(2)的所有权,赋值操作会先递减A(2)的引用计数,当计数降到0时,自动调用A(2)的析构函数销毁对象。
  • 你手里的a_raw是独立于shared_ptr的外部指针——shared_ptr不会主动修改它。对象销毁后,a_raw就成了野指针,此时访问它的val_属于未定义行为,输出0只是内存被回收后出现的随机结果(比如内存被清零或覆盖),完全不可预测。

简言之:shared_ptr只负责自己管控的对象生命周期,不会干预你手动维护的原始指针,对象销毁后原始指针指向的是无效内存,任何访问操作都没有意义。

2. 标准shared_ptr::operator=的核心逻辑

标准库的shared_ptr拷贝赋值运算符遵循以下关键步骤(简化版,实际包含异常安全、线程安全等细节):

  1. 先增新对象引用计数:对右值shared_ptr(比如a3)指向的对象,原子递增其引用计数。这一步是为了保证异常安全——如果后续操作抛出异常,新对象的引用计数不会出错,避免对象被错误销毁。
  2. 再减旧对象引用计数:对当前shared_ptr(比如a2)原来指向的对象,原子递减其引用计数。如果计数降到0,立即销毁该对象并释放对应内存。
  3. 更新当前指针与计数指针:将当前shared_ptr的原始指针替换为右值的原始指针,引用计数指针替换为右值的引用计数指针。
  4. 自我赋值保护:如果this == &rhs(即给自己赋值),直接返回*this,避免不必要的计数增减和对象销毁。

这里的「先增后减」是异常安全的关键——如果先减旧计数,后续操作失败的话,旧对象可能已经被销毁,而新对象还没完成接管,会导致资源泄漏或野指针问题。

3. 如何确认自定义shared_ptr拷贝赋值逻辑是否正确?

正确的拷贝赋值逻辑必须满足以下核心要求,你可以对照自己的代码检查:

  • 异常安全:必须先递增右值的引用计数,再处理当前对象的旧计数,不能颠倒顺序。
  • 自我赋值保护:必须判断是否是给自己赋值,是的话直接返回,避免重复操作。
  • 线程安全(可选):如果要支持多线程,引用计数的增减必须是原子操作;单线程场景下用普通整数即可,但也要保证操作的原子性(比如避免指令重排)。
  • 资源清理:当旧对象的引用计数降到0时,必须调用对象的析构函数并释放内存。

下面是一个符合要求的简化版实现示例:

template<typename T>
class shared_ptr {
private:
    T* ptr_ = nullptr;
    // 单线程用普通int,多线程用std::atomic<int>
    int* ref_count_ = nullptr;

    void increase_ref() {
        if (ref_count_) {
            ++(*ref_count_);
        }
    }

public:
    // 拷贝赋值运算符
    shared_ptr& operator=(const shared_ptr& rhs) {
        // 自我赋值检查
        if (this == &rhs) {
            return *this;
        }

        // 先递增右值的引用计数,保证异常安全
        rhs.increase_ref();

        // 处理当前对象的旧资源
        if (ref_count_) {
            --(*ref_count_);
            if (*ref_count_ == 0) {
                delete ptr_;
                delete ref_count_;
            }
        }

        // 更新指针和引用计数
        ptr_ = rhs.ptr_;
        ref_count_ = rhs.ref_count_;

        return *this;
    }

    // 其他构造、析构等函数省略...
};

内容的提问来源于stack exchange,提问作者mascai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:20:20