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

为何不能用同一裸指针初始化两个不同的shared_ptr?

为什么用同一原始指针创建两个shared_ptr会导致引用计数异常和崩溃?

先看你的问题代码:

#include<iostream>
#include<memory>
using namespace std;

class Base;

class Base {
public:
    int i;
    int j;
    Base(int _i, int _j) : i(_i), j(_j) {};
};

int main(void) {
    Base* q = new Base(5, 9);
    cout << q->i << endl;
    shared_ptr<Base> p(q);
    cout << p->j << endl;
    shared_ptr<Base> t(q);            // mark
    cout << p.use_count() << endl;
    // cout << t.use_count() << endl;
    return 0;
}

问题原因拆解:

  • shared_ptr的引用计数不是绑定在原始指针上,而是绑定在控制块里。当你用原始指针q创建第一个shared_ptr p时,会自动为q指向的对象生成一个控制块,里面的引用计数初始化为1。
  • 当你再用同一个q创建第二个shared_ptr t时,t无法感知到已经存在的控制块,它会重新创建一个完全独立的控制块,这个新控制块的引用计数也是1。现在就有两个控制块同时盯着同一块内存。
  • 程序结束时,p和t会依次被销毁:各自的控制块会把引用计数减到0,然后各自执行delete q。这就导致了同一块内存被重复释放,直接触发崩溃。而p.use_count()只统计自己控制块里的计数,所以输出1,不是你预期的2。

为什么改成shared_ptr t(p)就正常?

当你用p来初始化t时,调用的是shared_ptr的拷贝构造函数,它会直接复用p的控制块,把控制块里的引用计数加1。此时p和t共享同一个控制块,引用计数变成2。当它们销毁时,各自把计数减1,直到最后一个shared_ptr销毁时,才会执行一次delete操作,不会重复释放内存,所以程序运行正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:09:15