【AI大模型接入SDK】ChatSDK整体实现

🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • [1 ~> ChatSDK 整体实现](#1 ~> ChatSDK 整体实现)
    • [1.1 整体类结构](#1.1 整体类结构)
      • [1.1.1 ChatSDK 类核心成员](#1.1.1 ChatSDK 类核心成员)
      • [1.1.2 LLMManager 类职责](#1.1.2 LLMManager 类职责)
      • [1.1.3 继承配置体系 common.h](#1.1.3 继承配置体系 common.h)
    • [1.2 模型注册与初始化 initModels](#1.2 模型注册与初始化 initModels)
      • [1.2.1 registerAllProvider 模型注册阶段](#1.2.1 registerAllProvider 模型注册阶段)
        • [1.2.1.1 云端模型注册(deepseek‑chat /gpt‑4o‑mini /gemini‑2.0‑flash)](#1.2.1.1 云端模型注册(deepseek‑chat /gpt‑4o‑mini /gemini‑2.0‑flash))
        • [1.2.1.2 dynamic_pointer_cast 向下转型知识点](#1.2.1.2 dynamic_pointer_cast 向下转型知识点)
      • [1.2.2 initProviders 模型实例初始化阶段](#1.2.2 initProviders 模型实例初始化阶段)
        • [1.2.2.1 initAPIModelProviders 云端模型初始化](#1.2.2.1 initAPIModelProviders 云端模型初始化)
        • [1.2.2.2 initOllamaModelProviders Ollama 本地模型初始化](#1.2.2.2 initOllamaModelProviders Ollama 本地模型初始化)
    • [1.3 Session 会话管理实现](#1.3 Session 会话管理实现)
      • [1.3.1 createSession 创建会话](#1.3.1 createSession 创建会话)
      • [1.3.2 getSession 获取会话对象](#1.3.2 getSession 获取会话对象)
      • [1.3.3 getSessionLists 获取全部会话 ID 列表](#1.3.3 getSessionLists 获取全部会话 ID 列表)
      • [1.3.4 deleteSession 删除会话](#1.3.4 deleteSession 删除会话)
    • [1.4 消息发送接口实现](#1.4 消息发送接口实现)
      • [1.4.1 sendMessage 全量一次性返回应答](#1.4.1 sendMessage 全量一次性返回应答)
      • [1.4.2 sendMessageStream 流式增量回调返回](#1.4.2 sendMessageStream 流式增量回调返回)
  • [2 ~> 关键 C++ 核心易错点面试总结](#2 ~> 关键 C++ 核心易错点面试总结)
    • [2.1 unique_ptr 所有权转移](#2.1 unique_ptr 所有权转移)
    • [2.2 shared_ptr 多态向下转型](#2.2 shared_ptr 多态向下转型)
    • [2.3 云端模型 vs Ollama 本地模型差异对比](#2.3 云端模型 vs Ollama 本地模型差异对比)
  • [3 ~> ChatSDK 整体编译交付流程](#3 ~> ChatSDK 整体编译交付流程)
  • [4 ~> 完整业务调用时序(外部用户视角)](#4 ~> 完整业务调用时序(外部用户视角))
  • 结尾


1 ~> ChatSDK 整体实现

ChatSDK 对外提供统一接口,屏蔽云端大模型、本地 Ollama 模型差异;核心依赖LLMManager做模型管理,SessionManager管理会话上下文。整体工作流程:SDK 初始化模型 → 创建会话 session → 基于 session 发送消息(全量 / 流式增量返回)。

1.1 整体类结构

1.1.1 ChatSDK 类核心成员

  • 私有成员
    • bool _initialized:SDK 整体初始化标记位
    • LLMManager _llmManager:模型管理器,完成模型注册、实例初始化、消息下发
    • SessionManager _sessionManager:会话管理器,负责会话创建、删除、历史消息持久化
    • std::unordered_map<std::string, std::shared_ptr<Config>> _modelConfigs:保存各个模型对应的配置对象
  • 对外公开接口
    • initModels():批量注册并初始化模型,SDK 入口初始化函数
    • createSession():创建会话,返回 sessionId
    • getSession():根据 sessionId 获取会话对象
    • getSessionLists():获取全部会话 id 列表
    • deleteSession():删除指定会话
    • getAvailableModels():获取当前已经就绪可用模型列表
    • sendMessage():发送消息,全量一次性返回应答
    • sendMessageStream():发送消息,流式增量返回,回调推送分片数据
  • 私有内部辅助函数
    • registerAllProvider():遍历配置,注册全部模型 Provider
    • initProviders():遍历配置,调用对应初始化逻辑完成模型实例初始化
    • initAPIModelProviders():云端 API 模型初始化辅助函数
    • initOllamaModelProviders():本地 Ollama 模型初始化辅助函数

1.1.2 LLMManager 类职责

  1. 维护_providers:std::unordered_map<std::string, std::unique_ptr<LLMProvider>>,保存模型名称与 provider 实例独占指针
  2. 维护_modelInfos:保存每个模型运行状态、描述信息
  3. 核心接口
    1. registerProvider():注册 LLM 提供者,接收模型名 + unique_ptr<LLMProvider>,发生资源转移 std::move
    2. initModel():对已注册模型执行 provider 的initModel,完成模型实例初始化
    3. isModelAvailable():判断模型是否注册且初始化完成可用
    4. getAvailableModels():获取全部可用模型信息
    5. sendMessage():全量模式下发消息给底层 provider
    6. sendMessageStream():流式模式下发消息给底层 provider,传入回调

1.1.3 继承配置体系 common.h

多态配置,std::vector<std::shared_ptr<Config>>容器可以存放不同子类配置;基类必须定义虚析构,保证 dynamic_pointer_cast 安全向下转型

cpp 复制代码
//模型公共基类配置
struct Config{
    std::string _modelName;          //模型名称
    double _temperature = 0.7;       //生成随机性温度参数
    int _maxTokens = 2048;           //最大输出token
    virtual ~Config() = default;     //虚析构,多态向下转型dynamic_cast必备
};

//云端API模型配置:deepseek‑chat / gpt‑4o‑mini / gemini‑2.0‑flash
struct APIConfig : public Config{
    std::string _apikey;
};

//本地Ollama模型配置,不需要apikey,需要本地服务端点
struct OllamaConfig : public Config{
    std::string _modelDesc;          //模型描述
    std::string _endpoint;           //ollama服务地址,如http://127.0.0.1:11434
};

1.2 模型注册与初始化 initModels

ChatSDK::initModels() 外部调用入口,分为两大阶段:注册 Provider、初始化 Provider。

cpp 复制代码
bool ChatSDK::initModels(const std::vector<std::shared_ptr<Config>>& configs)
{
    registerAllProvider(configs);   //第一步:注册所有模型provider对象
    initProviders(configs);         //第二步:执行每个provider的初始化
    _initialized = true;
    return true;
}

1.2.1 registerAllProvider 模型注册阶段

1.2.1.1 云端模型注册(deepseek‑chat /gpt‑4o‑mini /gemini‑2.0‑flash)
  • 关键点:LLMManager::registerProvider入参是std::unique_ptr<LLMProvider>,unique_ptr 禁止拷贝,必须使用std::move将左值转为右值完成独占所有权转移。
  • 即使子类DeepSeekProvider公有继承基类LLMProvider,unique_ptr 不会执行隐式转换,必须显式 std::move。
cpp 复制代码
void ChatSDK::registerAllProvider(const std::vector<std::shared_ptr<Config>>& configs)
{
    //注册deepseek‑chat
    if(!_llmManager.isModelAvailable("deepseek‑chat")){
        auto deepseekProvider = std::make_unique<DeepSeekProvider>();
        //std::move转移独占所有权,不发生拷贝
        _llmManager.registerProvider("deepseek‑chat", std::move(deepseekProvider));
        INFO("deepseek‑chat provider registered successed");
    }

    //注册gpt‑4o‑mini
    if(!_llmManager.isModelAvailable("gpt‑4o‑mini")){
        auto gpt4oProvider = std::make_unique<ChatGPTProvider>();
        _llmManager.registerProvider("gpt‑4o‑mini", std::move(gpt4oProvider));
        INFO("gpt‑4o‑mini provider registered successed");
    }

    //注册gemini‑2.0‑flash
    if(!_llmManager.isModelAvailable("gemini‑2.0‑flash")){
        auto geminiProvider = std::make_unique<GeminiProvider>();
        _llmManager.registerProvider("gemini‑2.0‑flash", std::move(geminiProvider));
        INFO("gemini‑2.0‑flash provider registered successed");
    }

    //Ollama本地模型批量注册,来源于外部传入configs
    std::unordered_set<std::string> modelNames; //去重,避免重复注册同一个模型
    for(const auto& config : configs)
    {
        //安全向下转型:基类shared_ptr → 子类OllamaConfig shared_ptr
        auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config);
        if(ollamaConfig)
        {
            std::string modelName = ollamaConfig->_modelName;
            if(modelNames.find(modelName) == modelNames.end())
            {
                modelNames.insert(modelName);
                if(!_llmManager.isModelAvailable(modelName))
                {
                    auto ollamaProvider = std::make_unique<OllamaLLMProvider>();
                    _llmManager.registerProvider(modelName, std::move(ollamaProvider));
                    INFO("OllamaLLMProvider {} registered successed", modelName);
                }
            }
        }
    }
}
1.2.1.2 dynamic_pointer_cast 向下转型知识点
  • static_pointer_cast:不安全向下转型,不做运行时校验;如果原始对象不是目标子类,得到非法指针,UB 未定义行为。
  • dynamic_pointer_cast:安全多态向下转型,运行时 RTTI 校验;基类必须存在虚函数(虚析构);类型不匹配返回 nullptr。
  • 使用场景:容器存放基类shared_ptr<Config>,需要区分是APIConfig还是OllamaConfig。

1.2.2 initProviders 模型实例初始化阶段

遍历 configs,dynamic_cast 区分配置类型,分别调用initAPIModelProviders / initOllamaModelProviders。

cpp 复制代码
void ChatSDK::initProviders(const std::vector<std::shared_ptr<Config>>& configs)
{
    for(const auto& config : configs)
    {
        //尝试转型云端API配置
        if(auto apiConfig = std::dynamic_pointer_cast<APIConfig>(config))
        {
            if(apiConfig->_modelName == "deepseek‑chat"
                || apiConfig->_modelName == "gpt‑4o‑mini"
                || apiConfig->_modelName == "gemini‑2.0‑flash")
            {
                initAPIModelProviders(apiConfig->_modelName, apiConfig);
            }
            else
            {
                ERR("Model {} is not supported", apiConfig->_modelName);
            }
        }
        //尝试转型Ollama本地模型配置
        else if(auto ollamaConfig = std::dynamic_pointer_cast<OllamaConfig>(config))
        {
            initOllamaModelProviders(ollamaConfig->_modelName, ollamaConfig);
        }
        else
        {
            ERR("Config {} is not supported", config->_modelName);
        }
    }
}
1.2.2.1 initAPIModelProviders 云端模型初始化
  • 将 APIConfig 配置提取组装为std::map<std::string,std::string>参数,传给LLMManager::initModel
  • 云端模型 endpoint 可以内置默认值,用户传入配置可覆盖默认地址;必须校验 apikey 不为空。
cpp 复制代码
bool ChatSDK::initAPIModelProviders(const std::string& modelName, const std::shared_ptr<APIConfig>& apiConfig)
{
    if(modelName.empty()){
        ERR("ChatSDK::initAPIModelProviders:modelName is empty");
        return false;
    }
    if(!apiConfig || apiConfig->_apikey.empty()){
        ERR("ChatSDK::initAPIModelProviders:apikey is empty");
        return false;
    }
    if(!_llmManager.isModelAvailable(modelName)){
        ERR("ChatSDK::initAPIModelProviders:model {} is not available", modelName);
        return false;
    }

    std::map<std::string, std::string> modelParams;
    modelParams["api_key"] = apiConfig->_apikey;
    //endpoint:优先取用户配置,没有则使用内置厂商默认域名
    //modelParams["endpoint"] = apiConfig->_endpoint;

    if(!_llmManager.initModel(modelName, modelParams)){
        ERR("ChatSDK::initAPIModelProviders: init model failed {}", modelName);
        return false;
    }
    _modelConfigs[modelName] = apiConfig; //保存配置
    INFO("ChatSDK::initAPIModelProviders:model {} init successed", modelName);
    return true;
}
1.2.2.2 initOllamaModelProviders Ollama 本地模型初始化
  • Ollama 没有内置固定服务地址,model_name、model_desc、endpoint全部由外部配置传入,缺一不可。
cpp 复制代码
bool ChatSDK::initOllamaModelProviders(const std::string& modelName, const std::shared_ptr<OllamaConfig>& ollamaConfig)
{
    if(modelName.empty()){
        ERR("ChatSDK::initOllamaModelProviders:modelName is empty");
        return false;
    }
    if(!ollamaConfig || ollamaConfig->_endpoint.empty()){
        ERR("ChatSDK::initOllamaModelProviders:endpoint is empty");
        return false;
    }
    if(!_llmManager.isModelAvailable(modelName)){
        ERR("ChatSDK::initOllamaModelProviders:model {} is not available", modelName);
        return false;
    }

    std::map<std::string, std::string> modelParams;
    modelParams["model_name"] = modelName;
    modelParams["model_desc"] = ollamaConfig->_modelDesc;
    modelParams["endpoint"] = ollamaConfig->_endpoint;

    if(!_llmManager.initModel(modelName, modelParams)){
        ERR("ChatSDK::initOllamaModelProviders:init model failed {}", modelName);
        return false;
    }
    _modelConfigs[modelName] = ollamaConfig;
    INFO("ChatSDK::initOllamaModelProviders: model {} init successed", modelName);
    return true;
}

1.3 Session 会话管理实现

ChatSDK 会话相关接口全部转发调用SessionManager,每一个会话绑定一个模型,维护该会话完整消息历史。

1.3.1 createSession 创建会话

cpp 复制代码
std::string ChatSDK::createSession(const std::string& modelName)
{
    if(!_initialized){
        ERR("ChatSDK::createSession:SDK is not initialized");
        return "";
    }
    std::string sessionId = _sessionManager.createSession(modelName);
    if(sessionId.empty()){
        ERR("ChatSDK::createSession:create session failed");
        return "";
    }
    INFO("ChatSDK::createSession create session {} successed", sessionId);
    return sessionId;
}

1.3.2 getSession 获取会话对象

cpp 复制代码
std::shared_ptr<Session> ChatSDK::getSession(const std::string& sessionId)
{
    if(!_initialized){
        ERR("ChatSDK::getSession:SDK is not initialized");
        return nullptr;
    }
    auto session = _sessionManager.getSession(sessionId);
    if(!session){
        ERR("ChatSDK::getSession: session {} not found", sessionId);
    }
    return session;
}

1.3.3 getSessionLists 获取全部会话 ID 列表

cpp 复制代码
std::vector<std::string> ChatSDK::getSessionLists() const
{
    if(!_initialized){
        ERR("ChatSDK::getSessionLists: SDK is not initialized");
        return {};
    }
    return _sessionManager.getSessionLists();
}

1.3.4 deleteSession 删除会话

cpp 复制代码
bool ChatSDK::deleteSession(const std::string& sessionId)
{
    if(!_initialized){
        ERR("ChatSDK::deleteSession:SDK is not initialized");
        return false;
    }
    bool result = _sessionManager.deleteSession(sessionId);
    if(!result){
        ERR("ChatSDK::deleteSession:delete session failed {}", sessionId);
        return false;
    }
    INFO("ChatSDK::deleteSession:delete session {} successed", sessionId);
    return true;
}

1.4 消息发送接口实现

两个接口:全量返回sendMessage;流式增量返回sendMessageStream。 公共前置逻辑:

  1. 校验 SDK 初始化标记_initialized
  2. 根据 sessionId 获取会话 Session 对象
  3. 将用户输入 user 消息添加到会话
  4. 从 session 拿到绑定的 modelName,在_modelConfigs取出温度、max_tokens,组装请求参数
  5. 从 Session 读取完整历史消息
  6. 调用_llmManager底层接口发送请求
  7. 将 assistant 应答写入会话,更新会话时间戳

1.4.1 sendMessage 全量一次性返回应答

cpp 复制代码
std::string ChatSDK::sendMessage(const std::string& sessionId, const std::string& message)
{
    if(!_initialized){
        ERR("ChatSDK::sendMessage: SDK is not initialized");
        return "";
    }
    auto session = _sessionManager.getSession(sessionId);
    if(!session){
        ERR("ChatSDK::sendMessage: session not found {}", sessionId);
        return "";
    }

    // 1. 将用户消息加入会话
    Message userMessage{"user", message};
    _sessionManager.addMessage(sessionId, userMessage);
    // 2. 获取会话全部历史消息
    std::vector<Message> historyMessages = _sessionManager.getHistoryMessages(sessionId);

    // 3. 获取模型配置,组装请求参数
    auto it = _modelConfigs.find(session->_modelName);
    if(it == _modelConfigs.end()){
        ERR("ChatSDK::sendMessage:model {} not found", session->_modelName);
        return "";
    }
    std::map<std::string, std::string> requestParam;
    requestParam["temperature"] = std::to_string(it->second->_temperature);
    requestParam["max_tokens"] = std::to_string(it->second->_maxTokens);

    // 4. 调用LLMManager下发消息
    std::string response = _llmManager.sendMessage(session->_modelName, historyMessages, requestParam);
    if(response.empty()){
        ERR("ChatSDK::sendMessage: send message to model {} failed", session->_modelName);
        return "";
    }

    // 5. 将助手回复写入会话,更新会话时间戳
    Message assistantMessage{"assistant", response};
    _sessionManager.addMessage(sessionId, assistantMessage);
    _sessionManager.updateSessionTimestamp(sessionId);
    INFO("ChatSDK::sendMessage send message to model {} successed", session->_modelName);
    return response;
}

1.4.2 sendMessageStream 流式增量回调返回

  • 入参回调std::function<void(const std::string&, bool)> callback
    • 第一个参数:模型返回的增量分片字符串
    • 第二个 bool 参数:标记是否为最后一块分片
  • 底层 LLMManager 收到分片数据,反复调用回调推送数据;函数返回完整拼接后的应答文本。
cpp 复制代码
std::string ChatSDK::sendMessageStream(const std::string& sessionId, const std::string& message,
    std::function<void(const std::string&, bool)> callback)
{
    if(!_initialized){
        ERR("ChatSDK::sendMessageStream: SDK is not initialized");
        return "";
    }
    auto session = _sessionManager.getSession(sessionId);
    if(!session){
        ERR("ChatSDK::sendMessageStream:session not found {}", sessionId);
        return "";
    }

    Message userMessage{"user", message};
    _sessionManager.addMessage(sessionId, userMessage);
    std::vector<Message> historyMessages = _sessionManager.getHistoryMessages(sessionId);

    auto it = _modelConfigs.find(session->_modelName);
    if(it == _modelConfigs.end()){
        ERR("ChatSDK::sendMessageStream:model {} not found", session->_modelName);
        return "";
    }
    std::map<std::string, std::string> requestParam;
    requestParam["temperature"] = std::to_string(it->second->_temperature);
    requestParam["max_tokens"] = std::to_string(it->second->_maxTokens);

    std::string response = _llmManager.sendMessageStream(session->_modelName, historyMessages, requestParam, callback);
    if(response.empty()){
        ERR("ChatSDK::sendMessageStream:send message to model {} failed", session->_modelName);
        return "";
    }

    Message assistantMessage{"assistant", response};
    _sessionManager.addMessage(sessionId, assistantMessage);
    _sessionManager.updateSessionTimestamp(sessionId);
    INFO("ChatSDK::sendMessageStream send message to model {} successed", session->_modelName);
    return response;
}

2 ~> 关键 C++ 核心易错点面试总结

2.1 unique_ptr 所有权转移

  • unique_ptr是独占所有权智能指针,禁止拷贝构造、拷贝赋值 ,只允许移动语义std::move。
  • 即使子类指针可以隐式转换为基类裸指针,unique_ptr<SubClass>不会隐式转换 为unique_ptr<BaseClass>,必须显式std::move。
  • std::move只是将左值强制转换为右值引用,本身不做内存释放;移动之后源对象变为空。

2.2 shared_ptr 多态向下转型

  1. dynamic_pointer_cast<T>()
    1. 运行时 RTTI 检查,安全向下转型;要求基类必须存在虚函数(虚析构)。
    2. 类型不匹配,返回nullptr;可以用 if 判断转型结果。
  2. static_pointer_cast<T>()
    1. 编译期强制转换,无运行时检查;如果原始对象并不是目标子类,产生未定义行为 UB。

本项目Config基类添加virtual ~Config()=default;,目的就是为了支持dynamic_pointer_cast安全向下转型。

2.3 云端模型 vs Ollama 本地模型差异对比

项目 云端 API 模型(deepseek/gpt/gemini) Ollama 本地模型
鉴权 必须 apikey 不需要 apikey
服务端点 endpoint 代码内置默认值,用户可覆盖 必须外部配置传入,无默认值
模型名称 代码写死固定名称 完全由外部 config 配置传入,可以多个 ollama 模型
配置结构体 APIConfig OllamaConfig

3 ~> ChatSDK 整体编译交付流程

  1. 完成全部类代码实现:ChatSDK、LLMManager、SessionManager、各个 LLMProvider 实现类
  2. 将 SDK 编译为静态库 (.a)
  3. 对外交付:头文件 + 编译产出静态库
  4. 用户侧:引入头文件,链接静态库,构造vector<shared_ptr<Config>>配置,调用ChatSDK::initModels完成初始化,之后调用会话、发消息接口。

4 ~> 完整业务调用时序(外部用户视角)

  1. 构造std::vector<std::shared_ptr<Config>> configs,填入需要使用的模型配置(APIConfig/OllamaConfig)
  2. ChatSDK sdk; sdk.initModels(configs); 完成模型注册、初始化
  3. std::string sid = sdk.createSession("模型名称"); 创建会话
  4. 调用 sdk.sendMessage(sid, "用户提问") 或者 sdk.sendMessageStream(sid, "提问", callback) 进行对话
  5. 可选:getSessionLists查询会话,deleteSession销毁会话。

结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!" "技术之路难免有困惑,但同行的人会让前进更有方向。" |

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾:

【AI大模型接入SDK】ChatSDK架构设计与实现

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
我是小白呀1 小时前
19-Temporal项目实战:将客户开通流程迁移到持久执行架构
java·开发语言·人工智能·架构·workflow
励志不掉头发的内向程序员1 小时前
【从零写一个CAD 02】画完第一条线之后:实体容器、Esc 取消,和按了没反应的键盘
开发语言·c++·qt·学习·系统架构
独孤思维1 小时前
AI能赚钱,但是赚不了用户的心
人工智能·ai写作·副业·独孤思维·赚钱
l1t1 小时前
编译测试兼容gzip并行压缩解压工具pigz
c++·算法
IT·陈寒1 小时前
Java 并发这块坑真多,线程池又给我上了一课
人工智能·大模型·api·创业·变现·简历优化
Experience-摆渡1 小时前
谷歌WikiSkill论文精读:模型可以换经验留下来,9B反超27B
人工智能·深度学习
陈天伟教授1 小时前
DeepSeek Harness 6个使用技巧
人工智能·具身智能
promanz1 小时前
llamap.cpp 和 llama-index连接
人工智能·llama
无名猿1 小时前
对象存储期全解:automatic / static / dynamic / thread
c++·内存管理·现代c++·语法基础