为何std::shared_ptr会两次调用TC对象的析构函数?
为什么会出现两次析构调用?
你的问题核心出在这行代码的写法上:
std::shared_ptr<TC> stc = std::make_shared<TC>(TC());
我们一步步拆解这行代码的执行流程,就能搞懂两次析构的来龙去脉:
- 生成临时对象:
TC()会直接触发你写的默认构造函数,创建一个临时的TC实例——这就是你看到的TC Construct 0的来源,此时静态变量s_idx自增为1,这个临时对象的i_idx是0。 - 拷贝构造堆上实例:
std::make_shared<TC>(...)会把刚才的临时对象作为参数,调用编译器自动生成的默认拷贝构造函数(你没显式定义,编译器会帮你生成一个),在堆上创建另一个TC实例。这个默认拷贝构造不会打印任何内容,所以你看不到第二个Construct输出,但这个堆上实例的i_idx同样是0(因为默认拷贝会复制成员变量的值)。 - 临时对象被销毁:当这行代码执行完毕,临时对象的生命周期结束,会立刻调用析构函数——这就是第一次
TC Deconstruct 0的来源。 - shared_ptr管理的实例被销毁:当
setup()函数执行完成,stc这个shared_ptr超出作用域,它会销毁自己管理的堆上TC实例,于是第二次调用析构函数,输出TC Deconstruct 0。
修复方案
你完全不需要给make_shared传递TC(),直接让make_shared帮你创建实例即可,这样只会生成一个对象:
std::shared_ptr<TC> stc = std::make_shared<TC>();
修改后执行,你会看到符合预期的输出:
Setup start TC Construct 0 TC Deconstruct 0
只有当shared_ptr超出作用域时,才会调用一次析构函数。
内容的提问来源于stack exchange,提问作者hreintke
相关产品推荐
相关产品推荐

