为何std::any会触发对象析构函数两次调用?
std::any中对象析构两次的原因解析
你遇到的两次析构是完全正常的C++语义行为,根源在于代码中实际创建了两个foo对象实例:
执行流程拆解
当你写std::any any_foo = foo{};时,发生了以下步骤:
- 首先创建一个临时
foo对象,触发一次构造函数调用(ctor输出)。 - 这个临时对象被用来初始化
std::any内部存储的foo对象:如果没定义移动构造,会调用拷贝构造;如果定义了移动构造,则调用移动构造。 - 临时对象的生命周期在此处结束,触发第一次析构(
dtor输出)。 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
相关产品推荐
相关产品推荐

