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

如何用std::vector<std::any>存储不同类型的std::unique_ptr?

问题解决:用std::any存储不同类型std::unique_ptr

一、std::any方案完全可行,修改编译报错的代码

编译报错的核心原因是std::unique_ptr仅支持移动语义(不可拷贝),直接传递给vector::push_back时,编译器无法自动完成unique_ptr到std::any的转换(std::any的拷贝构造要求存储类型可拷贝,而移动构造需要显式触发)。

修改后的可编译代码如下:

#include <vector>
#include <any>
#include <memory>

class A
{
   int val;
};

class B
{
   float val;
};

int main()
{
    std::vector<std::any> vec;
    
    // 方式1:用std::make_unique创建后,转移所有权到std::any
    auto a = std::make_unique<A>();
    A& a_ref = *a; // 消费代码直接使用引用
    vec.push_back(std::move(a));
    
    // 方式2:直接在vector中构造std::any和unique_ptr,避免额外移动
    auto b = std::make_unique<B>();
    B& b_ref = *b;
    vec.emplace_back(std::move(b));
}

关键修改点:

  • 使用std::move显式转移unique_ptr的所有权到std::any中
  • 或用emplace_back直接在vector内部构造std::any,减少不必要的内存操作

二、其他轻量替代方案

如果不想依赖std::any,针对你"仅需自动清理对象、无需通过vector访问对象"的需求,还有两种更轻量化的选择:

1. 存储带自定义删除器的std::unique_ptr<void>

std::unique_ptr<void>本身无法自动销毁对象(因为不知道具体类型),但可以绑定自定义删除器,将销毁逻辑与对象指针绑定存储:

#include <vector>
#include <memory>

class A
{
   int val;
};

class B
{
   float val;
};

int main()
{
    // 存储void指针+对应类型的删除器
    std::vector<std::unique_ptr<void, void(*)(void*)>> vec;
    
    auto a = new A();
    A& a_ref = *a;
    // 绑定A类型的销毁逻辑
    vec.push_back(std::unique_ptr<void, void(*)(void*)>(a, [](void* p){ delete static_cast<A*>(p); }));
    
    auto b = new B();
    B& b_ref = *b;
    // 绑定B类型的销毁逻辑
    vec.push_back(std::unique_ptr<void, void(*)(void*)>(b, [](void* p){ delete static_cast<B*>(p); }));
}

这种方案无需引入std::any,内存开销更小,完全满足自动清理的需求。

2. 存储销毁函数的std::vector<std::function<void()>>

直接将对象的销毁逻辑封装成函数,vector销毁时自动执行所有清理函数:

#include <vector>
#include <functional>
#include <memory>

class A
{
   int val;
};

class B
{
   float val;
};

int main()
{
    std::vector<std::function<void()>> cleanup_list;
    
    auto a = new A();
    A& a_ref = *a;
    // 封装A的销毁逻辑
    cleanup_list.emplace_back([a](){ delete a; });
    
    auto b = new B();
    B& b_ref = *b;
    // 封装B的销毁逻辑
    cleanup_list.emplace_back([b](){ delete b; });
}

vector生命周期结束时,所有lambda会被依次执行,自动完成对象清理,逻辑简单直接。

总结

  • std::any方案完全可行,只需正确处理unique_ptr的移动语义
  • 若追求轻量高效,带自定义删除器的unique_ptr<void>或销毁函数列表是更优选择

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:05