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

关于std::map中std::shared_ptr<void>的使用疑问

为什么要使用std::shared_ptr<void>实现单词树?

代码示例

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <sstream>

using namespace std;

typedef std::map<std::string, std::shared_ptr<void>> M;
typedef std::vector<std::string> S;

void build_word_tree_from_sentences(const S& sentence_list, M& root)
{
    for (const auto& sentence : sentence_list)
    {
        std::string word;
        std::stringstream ss(sentence);
        M* base = &root;
        while (ss >> word)
        {
            auto found = base->find(word);
            if (found == base->end())
            {
                base->insert(std::make_pair(word, std::make_shared<M>()));
            }

            auto b = base->find(word)->second;
            base = std::static_pointer_cast<M>(b).get();
        }
    }
}

int main()
{
    S sentence_list = {"Hello word", "Hello there"};
    M tree;
    build_word_tree_from_sentences(sentence_list, tree);
}

问题

我理解std::shared_ptr的作用:它管理指针的存储,并通过自动释放已分配的内存实现有限的垃圾回收。但我不清楚为何要将其声明为std::shared_ptr<void>,查阅相关资料后仍未解决困惑。

解答

核心原因是绕开C++递归类型定义的限制:

  • 这里的M是表示单词树节点的类型,每个节点需要存储指向子节点(同样是M类型)的智能指针。如果直接把M定义成std::map<std::string, std::shared_ptr<M>>,编译器会报错——因为在定义M的时候,M本身还不是完整类型,无法用于声明shared_ptr<M>。
  • std::shared_ptr<void>在这里起到类型擦除的作用:它可以持有任意动态分配对象的shared_ptr,同时保留正确的析构逻辑(shared_ptr内部会保存对象的析构器,所以即使是shared_ptr<void>,也能在销毁时正确释放底层的M对象,不会出现内存泄漏)。
  • 代码里通过std::static_pointer_cast<M>把shared_ptr<void>转换回原本的shared_ptr<M>,就能正常访问子节点的map结构,实现树的递归构建。

简单说,这是C++里实现递归树形结构的一种妥协方案,用类型擦除避开编译器对不完整类型的限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:22:49