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

为什么C++中shared_ptr管理的A类对象在print调用前就被析构?

问题原因分析

核心错误:成员变量被局部变量遮蔽

你在B类的带参构造函数中声明了和成员变量同名的局部变量obj:

B(string s) {
    cout << "shared_ptr creation" <<endl;
    shared_ptr<A> obj = make_shared<A>(s); // 这里定义的是构造函数的局部obj,不是类的成员obj
    cout << "shared_ptr creation done" <<endl;
}
  • 你创建的shared_ptr<A>对象仅被这个局部变量持有,构造函数执行结束后局部变量销毁,对应A对象的引用计数降到0,所以直接被析构,这就是A对象在print调用前就销毁的直接原因。
  • 类B的成员obj全程没有被初始化,一直是空shared_ptr。

后续未定义行为

你调用func时采用值传递参数:

void func( B i) { i.print();}

值传递会调用B类的默认拷贝构造函数,把原对象b的空成员obj拷贝给参数i的成员。执行i.print()时对空shared_ptr执行->解引用属于未定义行为:

  • 你的运行结果中还能打印A print called只是巧合,因为A::print()没有访问任何类的成员变量,哪怕this指针为空也没有触发崩溃。如果print函数中访问了str成员,会直接触发段错误。

输出中两次销毁B的原因

你创建了两个B类对象:

  1. main块中定义的B b("hello world")
  2. func的值传递参数B i,是b的拷贝
    两个对象分别在离开func作用域、离开main内部块作用域时析构,所以会打印两次destroying B。
修复方案
  1. 构造函数中直接给成员变量赋值,不要重复声明局部变量,推荐用初始化列表写法:
B(string s) : obj(make_shared<A>(s)) {
    cout << "shared_ptr creation" <<endl;
    cout << "shared_ptr creation done" <<endl;
}
  1. 如果不需要修改参数,建议func改为传const引用,避免不必要的拷贝:
void func(const B& i) { i.print();}

修复后A对象的引用计数会被正确持有,直到B对象全部销毁后才会析构A对象,不会出现提前销毁和空指针解引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 21:36:04