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

为何std::any会触发对象析构函数两次调用?

std::any中对象析构两次的原因解析

你遇到的两次析构是完全正常的C++语义行为,根源在于代码中实际创建了两个foo对象实例:

执行流程拆解

当你写std::any any_foo = foo{};时,发生了以下步骤:

  1. 首先创建一个临时foo对象,触发一次构造函数调用(ctor输出)。
  2. 这个临时对象被用来初始化std::any内部存储的foo对象:如果没定义移动构造,会调用拷贝构造;如果定义了移动构造,则调用移动构造。
  3. 临时对象的生命周期在此处结束,触发第一次析构(dtor输出)。
  4. main函数执行完毕后,std::any对象any_foo被销毁,其内部存储的foo对象也随之销毁,触发第二次析构。

验证实例

给foo添加拷贝/移动构造的输出代码,可以清晰看到整个流程:

struct foo 
{
    foo() {std::cout << "ctor\n"; }
    foo(const foo&) {std::cout << "copy ctor\n"; }
    foo(foo&&) {std::cout << "move ctor\n"; }
    ~foo() {std::cout << "dtor\n"; }
};

int main() 
{    
    std::any any_foo = foo{}; 
    return 0;
}

运行输出会类似:

ctor
move ctor
dtor
dtor

两次析构分别对应临时对象和std::any内部的对象,不存在任何错误或内存泄漏。

关于五法则的补充

即使你实现了五法则(添加移动构造/赋值),依然会有两次析构——因为移动构造只是转移对象资源,并没有减少对象实例的数量,两个对象实例的生命周期结束时自然都会触发析构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:46:17