【DNN】基于llama.cpp的Qwen3-0.6B量化部署微调

目录

  • [1. LLAMA.CPP](#1. LLAMA.CPP)
    • [1.1 编译](#1.1 编译)
    • [1.2 验证编译结果](#1.2 验证编译结果)
  • [2. 配置CIONDA](#2. 配置CIONDA)
    • [2.1 国内镜像源](#2.1 国内镜像源)
    • [2.2 验证配置是否生效](#2.2 验证配置是否生效)
    • [2.3 更新 CONDA](#2.3 更新 CONDA)
  • [3. 量化环境配置](#3. 量化环境配置)
    • [3.1 虚拟环境](#3.1 虚拟环境)
    • [3.2 安装依赖](#3.2 安装依赖)
    • [3.4 模型量化](#3.4 模型量化)
    • [3.5 推理测试](#3.5 推理测试)
    • [3.6 模型部署](#3.6 模型部署)
  • [4 数据集](#4 数据集)
  • [5. 微调](#5. 微调)
    • [5.1 虚拟环境](#5.1 虚拟环境)
    • [5.3 train_lora.py](#5.3 train_lora.py)
    • [5.3 merge_lora.py](#5.3 merge_lora.py)
    • [5.4 LoRA](#5.4 LoRA)
    • [5.5 QLoRA](#5.5 QLoRA)

1. LLAMA.CPP

1.1 编译

bash 复制代码
cd ~/ws

git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp

# CPU
cmake -B        build_cpu -DCMAKE_INSTALL_PREFIX=install/cpu
cmake --build   build_cpu --config Release -j14
cmake --install build_cpu

# GPU
cmake -B        build_cuda -DGGML_CUDA=ON -DCMAKE_INSTALL_PREFIX=install/cuda
cmake --build   build_cuda --config Release -j14
cmake --install build_cuda

1.2 验证编译结果

bash 复制代码
# CPU
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cpu/lib
~/ws/llama.cpp/install/cpu/bin/llama-cli --version
# version: 9562 (8f83d6c27)
# built with GNU 11.4.0 for Linux x86_64

# GPU
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib
~/ws/llama.cpp/install/cuda/bin/llama-cli --version
# version: 9562 (8f83d6c27)
# built with GNU 11.4.0 for Linux x86_64

2. 配置CIONDA

2.1 国内镜像源

bash 复制代码
# 1. 删掉错误的源
conda config --remove-key channels

# 2. 配置最新可用的清华源(最稳定)
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge

# 3. 必须设置:不从官方 defaults 拉取(否则还是慢)
conda config --set default_channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --set show_channel_urls yes

# 4. 清除缓存
conda clean -i

2.2 验证配置是否生效

bash 复制代码
conda clean -i  # 清除旧缓存
conda info      # 查看通道信息,显示国内镜像地址即成功

2.3 更新 CONDA

bash 复制代码
conda update -n base conda

3. 量化环境配置

3.1 虚拟环境

bash 复制代码
conda create -n llama.cpp python=3.10
conda activate llama.cpp 

pip install modelscope
modelscope download --model Qwen/Qwen3-0.6B           --local_dir ~/ws/models/Qwen3-0.6B
modelscope download --model Qwen/Qwen3-VL-2B-Instruct --local_dir ~/ws/models/Qwen3-VL-2B-Instruct

3.2 安装依赖

bash 复制代码
cd llama.cpp
pip install -r requirements.txt

3.3 模型转换

bash 复制代码
cd ~/ws/llama.cpp
conda activate llama.cpp 

python convert_hf_to_gguf.py ~/ws/models/Qwen3-0.6B \
--outfile ~/ws/models/qwen3-0.6b-f16.gguf \
--outtype f16

3.4 模型量化

bash 复制代码
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib

~/ws/llama.cpp/install/cuda/bin/llama-quantize ~/ws/models/qwen3-0.6b-f16.gguf \
~/ws/models/qwen3-0.6b-q4_k_m.gguf \
Q4_K_M

3.5 推理测试

bash 复制代码
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib

~/ws/llama.cpp/install/cuda/bin/llama-cli \
-m ~/ws/models/qwen3-0.6b-q4_k_m.gguf \
-p "介绍C++17完美转发" \
-n 300 \
-ngl 99 \
-c 2048

3.6 模型部署

bash 复制代码
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib

~/ws/llama.cpp/install/cuda/bin/llama-server \
-m ~/ws/models/qwen3-0.6b-q4_k_m.gguf \
-ngl 99 \
-c 2048 \
-n 512 \
--host 0.0.0.0 \
--port 8080

curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
  "model": "qwen3",
  "messages": [
    {"role": "user", "content": "介绍C++17完美转发"}
  ],
  "temperature": 0.7,
  "max_tokens": 300
}'

4 数据集

json 复制代码
[
  {
    "instruction": "C++ 中 const 和 constexpr 有什么区别?",
    "input": "",
    "output": "const 表示变量不可修改,值可在运行时确定;constexpr 表示值必须在编译期可计算,用于常量表达式优化。"
  },
  {
    "instruction": "C++ 中 struct 和 class 有什么区别?",
    "input": "",
    "output": "默认访问权限不同:struct 默认 public,class 默认 private。除此之外功能完全相同,选择取决于语义习惯:POD 数据用 struct,封装逻辑用 class。"
  },
  {
    "instruction": "C++ 中 static 有哪些用法?",
    "input": "",
    "output": "三种用法:局部静态变量(函数内,只初始化一次,生命周期至程序结束);静态成员变量/函数(属于类而非实例);全局/文件静态(内部链接性,限制在本翻译单元可见)。"
  },
  {
    "instruction": "C++ 中 extern 关键字有什么作用?",
    "input": "",
    "output": "extern 声明变量或函数在其他翻译单元中定义,具有外部链接性;extern \"C\" 用于指定 C 语言链接约定,避免 C++ 名称修饰,常用于调用 C 库。"
  },
  {
    "instruction": "C++ 中 inline 关键字的含义是什么?",
    "input": "",
    "output": "inline 建议编译器内联展开函数调用以消除调用开销。现代 C++ 中 inline 更重要的语义是允许函数在头文件中定义而不违反 ODR 规则,编译器自行决定是否内联。"
  },
  {
    "instruction": "C++ 中 volatile 关键字有什么用?",
    "input": "",
    "output": "volatile 告诉编译器该变量可能被外部因素修改,禁止优化器缓存其值或重排访问顺序。常用于硬件寄存器映射和信号处理,不保证线程安全。"
  },
  {
    "instruction": "C++ 中 mutable 关键字有什么作用?",
    "input": "",
    "output": "mutable 允许 const 成员函数修改该成员变量。用于逻辑上不影响对象状态的缓存字段,如缓存计算结果。"
  },
  {
    "instruction": "C++ 中 explicit 关键字有什么用?",
    "input": "",
    "output": "explicit 禁止构造函数的隐式类型转换,只能显式调用。防止单参数构造函数导致的意外转换,C++11 起也适用于转换运算符。"
  },
  {
    "instruction": "C++ 中 typedef 和 using 有什么区别?",
    "input": "",
    "output": "typedef 是 C 遗留的类型别名机制;using 是 C++11 引入的别名声明,语法更清晰,支持模板别名(别名模板),功能更强大,推荐优先使用 using。"
  },
  {
    "instruction": "C++ 中 auto 关键字有什么作用?",
    "input": "",
    "output": "C++11 起 auto 让编译器根据初始化表达式推导变量类型。简化长类型名书写,配合范围 for 和 lambda 使用,不降低类型安全性。"
  },
  {
    "instruction": "C++ 中 decltype 关键字有什么用?",
    "input": "",
    "output": "decltype 推导表达式的类型而不实际计算表达式。常用于泛型编程中获取返回类型,如 decltype(auto) 或尾置返回类型声明。"
  },
  {
    "instruction": "C++ 中 nullptr 和 NULL 有什么区别?",
    "input": "",
    "output": "nullptr 是 C++11 引入的空指针常量,类型为 nullptr_t,不会与整数混淆;NULL 是宏定义,可能为 0 或 0L,在重载决议中可能匹配 int 参数导致歧义。"
  },
  {
    "instruction": "C++ 中 enum 和 enum class 有什么区别?",
    "input": "",
    "output": "enum 是 C 风格枚举,枚举值隐式转为整数,污染外层作用域;enum class 是 C++11 作用域枚举,枚举值不隐式转换,需用 EnumName::Value 访问,更安全。"
  },
  {
    "instruction": "C++ 中 sizeof 运算符有什么用?",
    "input": "",
    "output": "sizeof 返回类型或对象所占字节数,编译期求值。对数组返回整个数组大小,对指针返回指针大小。注意对齐和填充可能导致 sizeof 结果大于成员大小之和。"
  },
  {
    "instruction": "C++ 中 alignas 和 alignof 有什么用?",
    "input": "",
    "output": "alignas 指定变量或类型的对齐要求;alignof 查询类型的对齐要求。C++11 引入,用于 SIMD 和硬件相关的内存对齐需求。"
  },
  {
    "instruction": "C++ 中什么是聚合类型?",
    "input": "",
    "output": "聚合类型是没有用户声明构造函数、没有私有/保护非静态成员、没有虚函数、没有虚基类的类型。可用花括号初始化,C++17 起聚合检测更严格。"
  },
  {
    "instruction": "C++ 中什么是 POD 类型?",
    "input": "",
    "output": "POD(Plain Old Data)是兼容 C 内存布局的简单类型,具有平凡默认构造、平凡拷贝/移动、平凡析构函数。C++11 起用标准布局类型和平凡类型替代了 POD 概念。"
  },
  {
    "instruction": "C++ 中什么是平凡类型?",
    "input": "",
    "output": "平凡类型具有编译器生成的默认特殊成员函数,没有虚函数和虚基类,可安全地用 memcpy 拷贝。is_trivial_v<T> 可检测。"
  },
  {
    "instruction": "C++ 中什么是标准布局类型?",
    "input": "",
    "output": "标准布局类型具有与 C 兼容的内存布局,所有非静态成员同一访问权限,无虚函数和虚基类。is_standard_layout_v<T> 可检测。"
  },
  {
    "instruction": "C++ 中三法则是什么?",
    "input": "",
    "output": "如果类需要自定义析构函数、拷贝构造函数或拷贝赋值运算符中的任何一个,则通常需要自定义全部三个。因为管理资源时,三者语义紧密关联。"
  },
  {
    "instruction": "C++ 中五法则是什么?",
    "input": "",
    "output": "三法则的扩展,加入移动构造函数和移动赋值运算符。如果定义了任一特殊成员函数,应显式定义或删除全部五个,以确保资源管理语义一致。"
  },
  {
    "instruction": "C++ 中零法则是什么?",
    "input": "",
    "output": "零法则建议类不应声明任何特殊成员函数,通过使用智能指针和 RAII 类成员让编译器自动生成默认操作,实现自动正确的资源管理。"
  },
  {
    "instruction": "C++ 中什么是默认初始化?",
    "input": "",
    "output": "默认初始化调用默认构造函数。对于类类型调用默认构造;对于内置类型在全局/静态作用域初始化为零,在局部作用域不初始化(值不确定)。"
  },
  {
    "instruction": "C++ 中什么是值初始化?",
    "input": "",
    "output": "值初始化对内置类型初始化为零,对类类型调用默认构造函数。通过 T() 或 T{} 或花括号 {} 触发,比默认初始化更安全。"
  },
  {
    "instruction": "C++ 中什么是列表初始化?",
    "input": "",
    "output": "C++11 引入,用花括号 {} 进行初始化。不允许窄化转换(如 double 到 int),更安全。分为直接列表初始化 T{v} 和拷贝列表初始化 auto x = {v}。"
  },
  {
    "instruction": "C++ 中什么是最令人烦恼的解析?",
    "input": "",
    "output": "当声明看起来既像函数声明又像变量定义时,C++ 规定总是解析为函数声明。如 T t(T()) 声明了一个函数而非变量。用花括号 T t{T{}} 可避免。"
  },
  {
    "instruction": "C++ 中什么是复制消除?",
    "input": "",
    "output": "编译器优化技术,省略不必要的拷贝/移动构造。C++17 起对返回值优化(RVO)和传值初始化要求强制复制消除,保证不调用拷贝/移动构造函数。"
  },
  {
    "instruction": "C++ 中什么是内联变量?",
    "input": "",
    "output": "C++17 引入,inline 修饰变量允许在头文件中定义变量而不违反 ODR 规则,所有翻译单元共享同一实例。常用于类内静态成员变量定义。"
  },
  {
    "instruction": "C++ 中什么是结构化绑定?",
    "input": "",
    "output": "C++17 引入,auto [a, b, c] = expr 将元组、pair、数组或聚合类型的成员绑定到命名变量。简化多返回值处理,提高代码可读性。"
  },
  {
    "instruction": "C++ 中什么是 if constexpr?",
    "input": "",
    "output": "C++17 引入,编译期条件判断。条件为 false 的分支不会被实例化,用于模板元编程中根据类型条件选择不同代码路径,替代 SFINAE。"
  },
  {
    "instruction": "C++ 中什么是折叠表达式?",
    "input": "",
    "output": "C++17 引入,简化可变参数模板的递归展开。如 (args + ...) 是右折叠,(... + args) 是左折叠。支持 +、-、*、/、&&、|| 等二元运算符。"
  },
  {
    "instruction": "C++ 中什么是类模板参数推导 CTAD?",
    "input": "",
    "output": "C++17 引入,编译器可从构造函数参数推导类模板参数,如 vector v{1,2,3} 无需写 vector<int>。可自定义推导指引控制推导行为。"
  },
  {
    "instruction": "C++ 中什么是初始化语句?",
    "input": "",
    "output": "C++17 起 if 和 switch 可在条件前加初始化语句,如 if (auto it = m.find(key); it != m.end())。初始化变量的作用域限制在 if/else 块内。"
  },
  {
    "instruction": "C++ 中什么是嵌套命名空间?",
    "input": "",
    "output": "C++17 允许 namespace A::B::C { } 替代嵌套的 namespace A { namespace B { namespace C { } } },简化深层命名空间定义。"
  },
  {
    "instruction": "C++ 中什么是属性说明符?",
    "input": "",
    "output": "C++11 引入 [[attr]] 语法。标准属性包括 [[noreturn]]、[[carries_dependency]]、[[deprecated]]、[[fallthrough]]、[[nodiscard]]、[[maybe_unused]],提供编译器提示信息。"
  },
  {
    "instruction": "C++ 中 [[nodiscard]] 属性有什么用?",
    "input": "",
    "output": "标记函数返回值不可忽略,调用时若未使用返回值则编译器发出警告。用于重要返回值如错误码、分配结果,防止遗漏关键信息。"
  },
  {
    "instruction": "C++ 中 [[maybe_unused]] 属性有什么用?",
    "input": "",
    "output": "标记可能未使用的实体,抑制编译器未使用警告。用于条件编译中可能不用的参数或变量。"
  },
  {
    "instruction": "C++ 中 [[deprecated]] 属性有什么用?",
    "input": "",
    "output": "标记实体已废弃,使用时编译器发出警告。可附加消息说明替代方案,如 [[deprecated(\"use new_func()\")]]。"
  },
  {
    "instruction": "C++ 中什么是三路比较运算符?",
    "input": "",
    "output": "C++20 引入 <=> 运算符(太空船运算符),一次比较返回强序、偏序或弱序结果。编译器可自动生成 <、<=、>、>= 运算符,简化比较逻辑。"
  },
  {
    "instruction": "C++ 中什么是指定初始化器?",
    "input": "",
    "output": "C++20 引入,按名称初始化聚合成员,如 T{.x=1, .y=2}。源自 C99,提高初始化可读性,未指定的成员值初始化。"
  },
  {
    "instruction": "C++ 中什么是 constinit 关键字?",
    "input": "",
    "output": "C++20 引入,要求变量具有编译期初始化,避免静态初始化顺序问题。变量在编译期初始化,不产生运行时初始化开销,但不必是 const。"
  },
  {
    "instruction": "C++ 中什么是 consteval 关键字?",
    "input": "",
    "output": "C++20 引入,标记函数为立即函数,必须在编译期求值。比 constexpr 更严格,constexpr 函数可在编译期或运行期执行,consteval 只能编译期。"
  },
  {
    "instruction": "C++ 中什么是 concept?",
    "input": "",
    "output": "C++20 引入,对模板参数的命名约束。如 template<std::integral T> 限制 T 为整数类型。可组合、可诊断,替代 SFINAE 提供更清晰的错误信息。"
  },
  {
    "instruction": "C++ 中什么是 requires 子句?",
    "input": "",
    "output": "C++20 中 requires 用于约束模板:template<typename T> requires Concept<T> void f(T x)。也可用 requires { 表达式 } 定义内联约束。"
  },
  {
    "instruction": "C++ 中什么是模块(Modules)?",
    "input": "",
    "output": "C++20 引入,替代头文件的代码组织方式。module 声明模块,export 导出声明,import 导入模块。消除头文件重复编译、宏污染和包含顺序依赖。"
  },
  {
    "instruction": "C++ 中什么是协程(Coroutines)?",
    "input": "",
    "output": "C++20 引入协程语法,函数内使用 co_await、co_yield、co_return 暂停和恢复执行。语言只提供机制,库负责调度器等策略,需配合第三方库使用。"
  },
  {
    "instruction": "C++ 中什么是范围(Ranges)?",
    "input": "",
    "output": "C++20 引入 <ranges> 库,提供函数式管道操作。如 views::filter | views::transform,惰性求值,组合操作更优雅,替代手写循环。"
  },
  {
    "instruction": "C++ 中什么是 std::format?",
    "input": "",
    "output": "C++20 引入类型安全的格式化库,类似 Python 的 f-string。std::format(\"{} + {} = {}\", a, b, a+b),替代不安全的 printf 和繁琐的 iostream 拼接。"
  },
  {
    "instruction": "C++ 中什么是 std::source_location?",
    "input": "",
    "output": "C++20 引入,获取调用点的源文件名、行号、函数名等信息。替代 __FILE__、__LINE__ 宏,默认参数方式获取调用者位置信息。"
  },
  {
    "instruction": "C++23 有什么新特性?",
    "input": "",
    "output": "std::expected(错误处理)、std::print(格式化输出)、std::flat_map/flat_set(基于排序向量的容器)、deducing this(显式对象参数)、std::generator(协程生成器)、多维下标运算符等。"
  },
  {
    "instruction": "C++ 中什么是位域(bit-field)?",
    "input": "",
    "output": "位域指定结构体成员占用的位数,如 unsigned int x : 3 占 3 位。用于节省内存,但位域布局依赖实现,不可取地址。"
  },
  {
    "instruction": "C++ 中什么是联合体(union)?",
    "input": "",
    "output": "union 使所有成员共享同一内存,大小等于最大成员。C++ 中 union 可有构造/析构函数,但有非平凡成员时需手动管理生命周期。用 std::variant 更安全。"
  },
  {
    "instruction": "C++ 中什么是别名模板?",
    "input": "",
    "output": "C++11 起 using 可定义模板别名,如 template<typename T> using Vec = std::vector<T, MyAlloc<T>>。typedef 不支持模板,using 更灵活。"
  },
  {
    "instruction": "C++ 中什么是变参模板?",
    "input": "",
    "output": "C++11 引入,template<typename... Args> 允许模板接受任意数量类型参数。Args 称为参数包,可用 sizeof...(Args) 获取参数数量,通过递归或折叠展开。"
  },
  {
    "instruction": "C++ 中什么是变参宏?",
    "input": "",
    "output": "C 预处理器特性,__VA_ARGS__ 代表可变参数。如 #define LOG(fmt, ...) printf(fmt, __VA_ARGS__)。C++20 起有 __VA_OPT__ 处理空参数情况。"
  },
  {
    "instruction": "C++ 中什么是预处理指令?",
    "input": "",
    "output": "以 # 开头的编译前处理指令,包括 #include(包含文件)、#define(宏定义)、#ifdef/#endif(条件编译)、#pragma(编译器特定指令)等。"
  },
  {
    "instruction": "C++ 中 #pragma once 和头文件保护有什么区别?",
    "input": "",
    "output": "#pragma once 是编译器扩展,简单高效但非标准;头文件保护 #ifndef GUARD / #define GUARD / #endif 是标准方式,可移植。多数编译器支持 #pragma once。"
  },
  {
    "instruction": "C++ 中什么是名称查找?",
    "input": "",
    "output": "编译器根据名称查找对应声明。包括普通查找(从使用点向外层作用域搜索)、参数依赖查找 ADL(在参数所在命名空间搜索)和限定查找(通过 :: 指定)。"
  },
  {
    "instruction": "C++ 中什么是 ADL?",
    "input": "",
    "output": "参数依赖查找(Argument-Dependent Lookup),调用函数时除了普通查找,还在参数类型的命名空间中搜索函数。如 std::cout << x 能找到 operator<< 是因为 ADL。"
  },
  {
    "instruction": "C++ 中什么是名称修饰(name mangling)?",
    "input": "",
    "output": "C++ 编译器将函数名、参数类型等信息编码为唯一内部名称,支持函数重载和命名空间。不同编译器修饰规则不同,extern \"C\" 禁用修饰以兼容 C。"
  },
  {
    "instruction": "C++ 中什么是 ODR 规则?",
    "input": "",
    "output": "ODR(One Definition Rule)规定每个变量、函数、类在整个程序中只能有一个定义,违反会导致链接错误或未定义行为。内联函数和模板例外。"
  },
  {
    "instruction": "C++ 中什么是未定义行为?",
    "input": "",
    "output": "未定义行为(UB)是标准不规定结果的代码操作,如越界访问、解引用空指针、使用未初始化变量。编译器不做检查,后果不可预测,必须避免。"
  },
  {
    "instruction": "C++ 中什么是实现定义行为?",
    "input": "",
    "output": "实现定义行为由标准规定必须文档化,但具体行为由编译器决定。如 int 的大小、字节序。代码可移植但行为可能不同,需查阅编译器文档。"
  },
  {
    "instruction": "C++ 中什么是未指定行为?",
    "input": "",
    "output": "未指定行为是标准允许的多种合法行为之一,编译器可选择但不需文档化。如函数参数求值顺序。结果不确定但不会导致 UB。"
  },
  {
    "instruction": "C++ 中什么是 long long 类型?",
    "input": "",
    "output": "C++11 起保证 long long 至少 64 位整数。LL 后缀表示 long long 字面量。用于需要大整数范围的场景,如文件大小、时间戳。"
  },
  {
    "instruction": "C++ 中什么是 char8_t 类型?",
    "input": "",
    "output": "C++20 引入 char8_t 专门表示 UTF-8 字符,与 char 类型区分。u8 字符串字面量类型从 const char[] 变为 const char8_t[],避免与执行字符集混淆。"
  },
  {
    "instruction": "C++ 中什么是 std::byte 类型?",
    "input": "",
    "output": "C++17 引入 std::byte 表示原始字节,不参与算术运算,只支持位操作。替代 char/unsigned char 表示原始内存,语义更清晰。"
  },
  {
    "instruction": "C++ 中什么是字面量运算符?",
    "input": "",
    "output": "C++11 引入用户定义字面量,如 operator\"\"_km(long double) 使 3.5_km 成为合法表达式。用于物理单位、字符串处理等,提高代码可读性。"
  },
  {
    "instruction": "C++ 中什么是数字分隔符?",
    "input": "",
    "output": "C++14 引入单引号作为数字分隔符,如 1'000'000 表示一百万。不影响数值,仅提高可读性,编译时忽略。"
  },
  {
    "instruction": "C++ 中什么是二进制字面量?",
    "input": "",
    "output": "C++14 引入 0b 或 0B 前缀表示二进制字面量,如 0b1010 表示 10。配合数字分隔符 0b1101'0110 更清晰。"
  },
  {
    "instruction": "C++ 中什么是原始字符串字面量?",
    "input": "",
    "output": "R\"(内容)\" 格式,括号内字符原样保留,反斜杠不转义。适合正则表达式和文件路径,如 R\"(C:\\Users\\name)\" 无需双反斜杠。"
  },
  {
    "instruction": "C++ 中什么是 signed 和 unsigned?",
    "input": "",
    "output": "signed 表示有符号整数(可正可负),unsigned 表示无符号整数(非负)。unsigned 溢出是良定义的(取模运算),signed 溢出是未定义行为。混用需小心隐式转换。"
  },
  {
    "instruction": "C++ 中什么是类型转换?",
    "input": "",
    "output": "C++ 支持隐式转换(整型提升、算术转换)和显式转换。C++ 风格转换:static_cast(相关类型)、dynamic_cast(多态向下转型)、const_cast(去 const)、reinterpret_cast(位重解释)。"
  },
  {
    "instruction": "C++ 中 static_cast 有什么用?",
    "input": "",
    "output": "static_cast 用于相关类型间的转换,如 int 到 double、void* 到具体指针、向上转型。不做运行时检查,不安全向下转型后果未定义。"
  },
  {
    "instruction": "C++ 中 dynamic_cast 有什么用?",
    "input": "",
    "output": "dynamic_cast 用于多态类型的安全向下转型,运行时检查。引用转型失败抛 bad_cast,指针转型失败返回 nullptr。需要虚函数,有运行时开销。"
  },
  {
    "instruction": "C++ 中 const_cast 有什么用?",
    "input": "",
    "output": "const_cast 唯一能移除 const/volatile 修饰的转换。修改原本为 const 的对象是 UB。主要用于与不接受 const 的 C 接口交互。"
  },
  {
    "instruction": "C++ 中 reinterpret_cast 有什么用?",
    "input": "",
    "output": "reinterpret_cast 在不相关指针/引用类型间做位级重解释。如 int* 到 char*。结果依赖实现,除特定场景外不保证可移植。最危险的转换,慎用。"
  },
  {
    "instruction": "C++ 中什么是整型提升?",
    "input": "",
    "output": "小整型(bool、char、short)在表达式中自动提升为 int 或 unsigned int。确保运算不会溢出小类型范围。如 char a=1,b=2; auto c=a+b; c 是 int 而非 char。"
  },
  {
    "instruction": "C++ 中什么是函数重载?",
    "input": "",
    "output": "同一作用域中同名函数有不同的参数类型或数量,编译器根据调用参数选择最佳匹配。返回类型不参与重载决议。C++ 不支持仅返回类型不同的重载。"
  },
  {
    "instruction": "C++ 中什么是名称隐藏?",
    "input": "",
    "output": "派生类中声明的名称隐藏基类中的同名成员,不论签名是否相同。用 using Base::func 或限定名 Base::func 恢复基类名称可见性。"
  },
  {
    "instruction": "C++ 中什么是作用域解析运算符?",
    "input": "",
    "output": ":: 用于指定命名空间或类的成员。全局作用域 ::var、命名空间 ns::var、类成员 Class::member。也用于定义类外成员函数。"
  },
  {
    "instruction": "C++ 中什么是 using 声明和 using 指令?",
    "input": "",
    "output": "using 声明:using ns::func 引入特定名称;using 指令:using namespace ns 引入整个命名空间。声明更安全(不污染命名空间),指令更方便但易冲突。"
  },
  {
    "instruction": "C++ 中什么是匿名命名空间?",
    "input": "",
    "output": "namespace { ... } 中的名称具有内部链接性,等价于 static 全局变量。每个翻译单元有独立的匿名命名空间实例,用于限制符号可见性。"
  },
  {
    "instruction": "C++ 中什么是信号?",
    "input": "",
    "output": "信号是操作系统发送给进程的异步通知,如 SIGINT(Ctrl+C)、SIGSEGV(段错误)。C++ 中可用 <csignal> 的 signal() 注册处理函数,但处理函数中只能调用异步安全函数。"
  },
  {
    "instruction": "C++ 中什么是 main 函数的签名?",
    "input": "",
    "output": "标准签名:int main() 或 int main(int argc, char* argv[])。argv[0] 是程序名,argv[argc] 是 nullptr。返回 0 表示成功,非零表示失败。"
  },
  {
    "instruction": "C++ 中什么是预处理运算符 # 和 ##?",
    "input": "",
    "output": "# 将宏参数转为字符串,如 #var 变为 \"var\";## 拼接两个标记,如 a##b 变为 ab。用于元编程和代码生成。"
  },
  {
    "instruction": "C++ 中什么是 RAII?",
    "input": "",
    "output": "RAII 即资源获取即初始化,利用对象生命周期管理资源:构造时获取资源,析构时释放资源,确保异常安全。"
  },
  {
    "instruction": "C++ 中如何避免内存泄漏?",
    "input": "",
    "output": "使用智能指针替代裸指针;遵循 RAII 原则;使用工具如 Valgrind、AddressSanitizer 检测;避免手动 new/delete,优先用栈对象和容器。"
  },
  {
    "instruction": "C++ 中什么是智能指针?",
    "input": "",
    "output": "智能指针是自动管理内存的包装类。C++ 有三种:unique_ptr(独占所有权)、shared_ptr(共享引用计数)、weak_ptr(不增加引用计数,避免循环引用)。"
  },
  {
    "instruction": "C++ 中 unique_ptr 有什么特点?",
    "input": "",
    "output": "unique_ptr 独占所指向对象的所有权,不可复制只可移动。离开作用域自动删除对象。开销极小,与裸指针性能相当,是默认的智能指针选择。"
  },
  {
    "instruction": "C++ 中 shared_ptr 有什么特点?",
    "input": "",
    "output": "shared_ptr 通过引用计数共享对象所有权。最后一个 shared_ptr 析构时删除对象。线程安全的引用计数操作,但对象访问需额外同步。"
  },
  {
    "instruction": "C++ 中 weak_ptr 有什么特点?",
    "input": "",
    "output": "weak_ptr 是 shared_ptr 的观察者,不增加引用计数。用 lock() 获取 shared_ptr 访问对象。用于打破循环引用、缓存和观察者模式。"
  },
  {
    "instruction": "C++ 中什么是循环引用?如何解决?",
    "input": "",
    "output": "两个 shared_ptr 互相持有导致引用计数永不为零,内存泄漏。解决方案:将一方改为 weak_ptr 打破循环,或使用裸指针/引用表示非所有权关系。"
  },
  {
    "instruction": "C++ 中 make_unique 和 make_shared 有什么优势?",
    "input": "",
    "output": "避免裸指针和 new;单次分配内存(make_shared 合并控制块和对象);异常安全,防止 new 和构造函数之间的资源泄漏。C++14 引入 make_unique。"
  },
  {
    "instruction": "C++ 中什么是自定义删除器?",
    "input": "",
    "output": "智能指针可在构造时指定删除器,如 unique_ptr<FILE, decltype(&fclose)> p(fopen(...), fclose)。用于管理非 new 分配的资源如文件句柄、套接字。"
  },
  {
    "instruction": "C++ 中 new 和 malloc 有什么区别?",
    "input": "",
    "output": "new 调用构造函数、返回类型指针、失败抛异常、可重载;malloc 只分配内存、返回 void*、失败返回 NULL、不可重载。C++ 中应优先使用 new。"
  },
  {
    "instruction": "C++ 中 delete 和 free 有什么区别?",
    "input": "",
    "output": "delete 调用析构函数后释放内存,与 new 配对;free 只释放内存,与 malloc 配对。不可混用,delete[] 用于数组,free 无此区分。"
  },
  {
    "instruction": "C++ 中 placement new 有什么用?",
    "input": "",
    "output": "placement new 在已分配的内存上构造对象,不分配新内存。如 new (buffer) T(args)。需手动调用析构函数,用于内存池和自定义分配器。"
  },
  {
    "instruction": "C++ 中 operator new 可以重载吗?",
    "input": "",
    "output": "可以。可重载全局 operator new/delete 或类专属版本,实现自定义内存分配策略如内存池、对齐分配、统计分配次数等。"
  },
  {
    "instruction": "C++ 中什么是内存对齐?",
    "input": "",
    "output": "处理器要求数据地址是其大小的整数倍。未对齐访问可能降低性能或崩溃。alignof 查询对齐要求,alignas 指定对齐,new 返回的内存默认对齐。"
  },
  {
    "instruction": "C++ 中什么是内存池?",
    "input": "",
    "output": "预分配大块内存,从中分配小块,避免频繁调用系统分配器。减少内存碎片和分配开销,适合大量小对象的场景。可自定义 allocator 实现。"
  },
  {
    "instruction": "C++ 中什么是栈和堆?",
    "input": "",
    "output": "栈:自动管理,后进先出,分配释放快,空间有限;堆:手动管理(或智能指针),分配释放慢,空间大但可能碎片化。优先使用栈分配。"
  },
  {
    "instruction": "C++ 中什么是悬垂指针?",
    "input": "",
    "output": "指向已释放内存的指针。解引用悬垂指针是未定义行为。使用智能指针、引用生命周期分析和工具检测来避免。"
  },
  {
    "instruction": "C++ 中什么是野指针?",
    "input": "",
    "output": "未初始化的指针,指向随机地址。解引用野指针是未定义行为。声明指针时立即初始化为 nullptr 或有效地址可避免。"
  },
  {
    "instruction": "C++ 中什么是双重释放?",
    "input": "",
    "output": "对同一内存调用两次 delete,导致堆损坏。使用智能指针或确保 delete 后置 nullptr 可避免。AddressSanitizer 可检测。"
  },
  {
    "instruction": "C++ 中什么是浅拷贝和深拷贝?",
    "input": "",
    "output": "浅拷贝复制指针值,多个对象指向同一内存;深拷贝复制指针指向的内容,每个对象有独立内存。管理资源时必须实现深拷贝或禁用拷贝。"
  },
  {
    "instruction": "C++ 中什么是移动语义?",
    "input": "",
    "output": "C++11 引入,通过移动构造/移动赋值窃取资源而非拷贝,避免不必要的深拷贝。用 std::move 将左值转为右值引用触发移动操作。"
  },
  {
    "instruction": "C++ 中什么是移动构造函数?",
    "input": "",
    "output": "移动构造函数接受右值引用参数 T(T&& other),通过窃取资源(如指针)而非深拷贝来构造新对象,源对象置于可析构状态,大幅提升性能。"
  },
  {
    "instruction": "C++ 中什么是移动赋值运算符?",
    "input": "",
    "output": "T& operator=(T&& other),先释放当前资源,再窃取源对象资源,将源对象置空。需处理自赋值和异常安全。"
  },
  {
    "instruction": "C++ 中 std::move 做了什么?",
    "input": "",
    "output": "std::move 将左值强制转换为右值引用,本身不移动任何东西。它只是类型转换,使移动构造/赋值被调用,实际移动在构造/赋值函数中完成。"
  },
  {
    "instruction": "C++ 中什么是完美转发?",
    "input": "",
    "output": "完美转发使用 std::forward 保持参数的值类别(左值/右值),配合万能引用 T&&,使转发给其他函数时保留原始参数的左值或右值特性。"
  },
  {
    "instruction": "C++ 中什么是万能引用?",
    "input": "",
    "output": "Scott Meyers 提出的概念,T&& 在类型推导上下文中既可绑定左值也可绑定右值。推导为左值时 T 为 U&,T&& 折叠为 U&;推导为右值时 T 为 U,T&& 为 U&&。"
  },
  {
    "instruction": "C++ 中什么是引用折叠?",
    "input": "",
    "output": "模板实例化时引用的引用按规则折叠:左值引用的任何引用为左值引用,只有右值引用的右值引用为右值引用。即 T& & → T&,T& && → T&,T&& & → T&,T&& && → T&&。"
  },
  {
    "instruction": "C++ 中什么是值类别?",
    "input": "",
    "output": "C++11 起值类别分为:左值(有身份不可移动)、亡值(有身份可移动,如返回右值引用)、纯右值(无身份可移动,如临时对象)。左值和亡值合称泛左值,亡值和纯右值合称右值。"
  },
  {
    "instruction": "C++ 中什么是返回值优化 RVO?",
    "input": "",
    "output": "编译器省略函数返回值的拷贝/移动构造,直接在调用者的栈帧构造对象。C++17 起对纯右值初始化要求强制 RVO,命名返回值优化 NRVO 仍可选。"
  },
  {
    "instruction": "C++ 中什么是小型对象优化 SSO?",
    "input": "",
    "output": "std::string 等类型在对象内部存储短字符串,避免堆分配。通常 15-22 字节以内使用内部缓冲区,超出才分配堆内存。大幅提升短字符串性能。"
  },
  {
    "instruction": "C++ 中 allocator 有什么用?",
    "input": "",
    "output": "allocator 是 STL 容器的内存分配策略接口,将内存分配与对象构造分离。可自定义 allocator 实现内存池、共享内存、对齐分配等特殊需求。"
  },
  {
    "instruction": "C++ 中什么是 pmr?",
    "input": "",
    "output": "C++17 引入多态内存资源(Polymorphic Memory Resource),如 memory_resource 基类、synchronized_pool_resource、unsynchronized_pool_resource。容器通过 pmr 分配器使用运行时选择的内存资源。"
  },
  {
    "instruction": "C++ 中如何检测内存泄漏?",
    "input": "",
    "output": "使用 Valgrind 的 memcheck 工具;编译时加 -fsanitize=address 使用 AddressSanitizer;运行时用 _CrtDumpMemoryLeaks(MSVC);代码审查确保 RAII 和智能指针使用。"
  },
  {
    "instruction": "C++ 中什么是智能指针的别名构造?",
    "input": "",
    "output": "shared_ptr 的别名构造函数 shared_ptr(shared_ptr<U>, T*),共享 U 的引用计数但指向 T 成员。用于指向 shared_ptr 管理对象的成员,确保宿主对象不被释放。"
  },
  {
    "instruction": "C++ 中 enable_shared_from_this 有什么用?",
    "input": "",
    "output": "允许在对象的成员函数中安全获取指向自身的 shared_ptr。继承 enable_shared_from_this<T>,调用 shared_from_this()。对象必须已被 shared_ptr 管理。"
  },
  {
    "instruction": "C++ 中 unique_ptr 可以用于数组吗?",
    "input": "",
    "output": "可以,unique_ptr<T[]> 管理数组,用 delete[] 释放。C++11 支持,但更推荐使用 std::vector 或 std::array 替代。"
  },
  {
    "instruction": "C++ 中 shared_ptr 的引用计数是线程安全的吗?",
    "input": "",
    "output": "引用计数的增减是原子操作,线程安全。但 shared_ptr 指向对象的并发访问不是线程安全的,需要额外同步。shared_ptr 本身的拷贝/赋值也是线程安全的。"
  },
  {
    "instruction": "C++ 中什么是缓存友好代码?",
    "input": "",
    "output": "利用局部性原理:数据连续存储(用 vector 而非 list);数据结构对齐缓存行(64字节);减少指针追踪;数据布局优化(AoS vs SoA)。"
  },
  {
    "instruction": "C++ 中什么是虚函数表 vtable?",
    "input": "",
    "output": "编译器为含虚函数的类生成虚函数表,存储虚函数指针。每个对象含指向 vtable 的指针(vptr),运行时通过 vptr 查 vtable 实现动态分发。"
  },
  {
    "instruction": "C++ 中对象的内存布局是怎样的?",
    "input": "",
    "output": "非静态成员按声明顺序排列,可能有填充字节满足对齐;虚类有 vptr(通常在开头);多重继承有多个 vptr;虚基类通过虚基类表或偏移访问。布局依赖实现。"
  },
  {
    "instruction": "C++ 中什么是空基类优化 EBO?",
    "input": "",
    "output": "空类大小为 1 字节(C++ 要求每个对象有唯一地址),但作为基类时可占 0 字节。STL 如 std::allocator 利用 EBO 减少容器大小。"
  },
  {
    "instruction": "C++ 中 new 失败会怎样?",
    "input": "",
    "output": "默认抛出 std::bad_alloc 异常。可用 std::nothrow 版本 new(std::nothrow) 返回 nullptr。可设置 new_handler 自定义失败处理。"
  },
  {
    "instruction": "C++ 中什么是栈展开?",
    "input": "",
    "output": "异常抛出后,运行时从当前点向外层逐帧销毁局部对象(调用析构函数),直到找到匹配的 catch。析构函数不应抛异常,否则调用 std::terminate。"
  },
  {
    "instruction": "C++ 中如何限制对象只能在堆上创建?",
    "input": "",
    "output": "将析构函数设为 private 或 protected,提供 public 的 destroy() 方法。这样栈对象无法隐式析构,只能通过 new 创建并通过 destroy() 删除。"
  },
  {
    "instruction": "C++ 中如何限制对象只能在栈上创建?",
    "input": "",
    "output": "将 operator new 设为 private 或 delete。如 void* operator new(size_t) = delete; 禁止 new 表达式,对象只能作为栈变量或成员创建。"
  },
  {
    "instruction": "C++ 中什么是 std::launder?",
    "input": "",
    "output": "C++17 引入,告诉编译器指针可能指向在相同地址重新创建的对象。用于 placement new 后通过旧指针访问新对象的场景,防止优化器假设对象未变。"
  },
  {
    "instruction": "C++ 中什么是 std::construct_at 和 std::destroy_at?",
    "input": "",
    "output": "C++20 引入的未初始化内存操作。construct_at 在给定地址构造对象,destroy_at 调用析构函数。比 placement new 和显式析构调用更规范,支持 constexpr。"
  },
  {
    "instruction": "C++ 中什么是 std::optional?",
    "input": "",
    "output": "C++17 引入,表示可能没有值的对象。如 optional<int> 可包含 int 值或为空。用 has_value() 检查,value() 或 * 访问,替代哨兵值和裸指针。"
  },
  {
    "instruction": "C++ 中什么是 std::variant?",
    "input": "",
    "output": "C++17 引入,类型安全的联合体。如 variant<int, string> 可持有 int 或 string。用 holds_alternative/visit 访问,比 union 更安全。"
  },
  {
    "instruction": "C++ 中什么是 std::any?",
    "input": "",
    "output": "C++17 引入,可持有任意类型单个值的类型安全容器。用 any_cast<T> 访问,运行时检查类型。比 void* 安全,但有运行时开销。"
  },
  {
    "instruction": "C++ 中什么是 std::expected?",
    "input": "",
    "output": "C++23 引入,表示可能包含值或错误的对象。如 expected<int, Error> 返回值或错误。比异常轻量,比返回码更结构化,替代抛异常的错误处理。"
  },
  {
    "instruction": "C++ 中什么是 shared_ptr 的控制块?",
    "input": "",
    "output": "shared_ptr 的控制块存储强引用计数、弱引用计数、自定义删除器和分配器。make_shared 将控制块和对象合并分配,减少一次内存分配。"
  },
  {
    "instruction": "C++ 中什么是内存碎片?",
    "input": "",
    "output": "内存碎片分为外部碎片(空闲内存不连续,无法满足大块分配)和内部碎片(分配块大于请求大小)。内存池和自定义分配器可缓解碎片问题。"
  },
  {
    "instruction": "C++ 中什么是 over-aligned 类型?",
    "input": "",
    "output": "对齐要求超过 std::max_align_t(通常 16 字节)的类型,如 SIMD 向量要求 32/64 字节对齐。C++17 起 operator new 支持对齐参数,new T 自动处理 over-aligned 分配。"
  },
  {
    "instruction": "C++ 中什么是 std::aligned_alloc?",
    "input": "",
    "output": "C++17 引入的对齐分配函数,分配指定对齐和大小的内存。替代平台特定的 _aligned_malloc 和 posix_memalign,跨平台统一接口。"
  },
  {
    "instruction": "C++ 中什么是内存屏障?",
    "input": "",
    "output": "内存屏障(memory barrier/fence)防止编译器和处理器重排内存操作。C++11 通过 std::atomic 的内存序(memory_order)提供可移植的屏障语义。"
  },
  {
    "instruction": "C++ 中什么是垃圾回收?C++ 支持吗?",
    "input": "",
    "output": "C++ 标准不要求垃圾回收器,但规定了安全派生指针规则允许实现 GC。实践中 C++ 依赖 RAII 和智能指针管理内存,而非垃圾回收。"
  },
  {
    "instruction": "C++ 中什么是侵入式引用计数?",
    "input": "",
    "output": "引用计数存储在对象内部而非独立控制块。如 COM 的 AddRef/Release。比 shared_ptr 少一次内存分配,但需修改对象类型,不如 shared_ptr 通用。"
  },
  {
    "instruction": "C++ 中如何实现自定义分配器?",
    "input": "",
    "output": "继承 std::allocator_traits 或实现 allocate/deallocate 接口。需提供 value_type、allocate(n)、deallocate(p,n) 等成员。C++11 起简化了要求。"
  },
  {
    "instruction": "C++ 中什么是封装?",
    "input": "",
    "output": "封装将数据和方法绑定在一起,隐藏内部实现细节,通过访问说明符(public/protected/private)控制外部访问。提高代码安全性和可维护性。"
  },
  {
    "instruction": "C++ 中什么是继承?",
    "input": "",
    "output": "继承允许派生类获得基类的成员和行为,实现代码复用和层次化设计。支持单继承和多继承,可通过 virtual 继承解决菱形问题。"
  },
  {
    "instruction": "C++ 中什么是多态?",
    "input": "",
    "output": "多态允许同一接口不同实现。编译期多态通过模板和重载实现;运行期多态通过虚函数和基类引用/指针实现,运行时根据实际对象类型调用对应方法。"
  },
  {
    "instruction": "C++ 中虚函数的工作原理是什么?",
    "input": "",
    "output": "含虚函数的类有虚函数表(vtable),每个对象有指向 vtable 的虚指针(vptr)。调用虚函数时通过 vptr 查 vtable 确定实际函数地址,实现动态绑定。"
  },
  {
    "instruction": "C++ 中纯虚函数和抽象类是什么?",
    "input": "",
    "output": "纯虚函数用 =0 声明,没有默认实现(C++11 起可有)。含纯虚函数的类是抽象类,不可实例化。派生类必须实现所有纯虚函数才能成为具体类。"
  },
  {
    "instruction": "C++ 中 override 关键字有什么用?",
    "input": "",
    "output": "C++11 引入,显式标记派生类函数覆盖基类虚函数。若签名不匹配则编译报错,防止因签名错误导致的意外隐藏而非覆盖。"
  },
  {
    "instruction": "C++ 中 final 关键字有什么用?",
    "input": "",
    "output": "C++11 引入,标记类不可被继承或虚函数不可被覆盖。如 class A final 或 virtual void f() final,编译器检查并阻止违反。"
  },
  {
    "instruction": "C++ 中什么是虚继承?",
    "input": "",
    "output": "virtual 继承解决菱形继承中基类子对象重复问题。虚继承的基类由最远派生类构造一次,所有虚派生路径共享同一基类子对象。"
  },
  {
    "instruction": "C++ 中什么是菱形继承?",
    "input": "",
    "output": "D 继承 B 和 C,B 和 C 都继承 A,D 中有两个 A 子对象。用虚继承 class B : virtual public A 使 D 只有一个 A 子对象。"
  },
  {
    "instruction": "C++ 中构造函数可以抛异常吗?",
    "input": "",
    "output": "可以,但对象不会完全构造,析构函数不会被调用。需在构造函数中手动释放已获取的资源,或使用 RAII 成员自动释放。"
  },
  {
    "instruction": "C++ 中析构函数应该抛异常吗?",
    "input": "",
    "output": "不应该。析构函数抛异常会导致栈展开时调用 std::terminate。析构函数应捕获并处理所有内部异常,确保 noexcept 语义。"
  },
  {
    "instruction": "C++ 中构造函数的执行顺序是什么?",
    "input": "",
    "output": "1. 基类构造(按继承声明顺序);2. 成员变量构造(按声明顺序);3. 构造函数体执行。析构顺序相反。"
  },
  {
    "instruction": "C++ 中什么是委托构造?",
    "input": "",
    "output": "C++11 引入,一个构造函数调用同类的另一个构造函数。如 A(int x) : A(x, 0) {} 委托给 A(int, int)。避免构造函数间代码重复。"
  },
  {
    "instruction": "C++ 中什么是继承构造?",
    "input": "",
    "output": "C++11 引入 using Base::Base 让派生类继承基类构造函数。避免为每个基类构造函数写转发包装。但不会继承默认参数和 explicit 属性。"
  },
  {
    "instruction": "C++ 中什么是默认构造函数?",
    "input": "",
    "output": "无参数或所有参数都有默认值的构造函数。未声明任何构造函数时编译器自动生成。一旦声明其他构造函数,默认构造函数不再自动生成。"
  },
  {
    "instruction": "C++ 中什么是拷贝构造函数?",
    "input": "",
    "output": "接受同类对象引用的构造函数 T(const T&)。用于对象初始化、函数传值参数、函数返回值。默认实现逐成员拷贝。"
  },
  {
    "instruction": "C++ 中什么是拷贝赋值运算符?",
    "input": "",
    "output": "T& operator=(const T&),将已有对象赋值为另一个对象的副本。需处理自赋值、释放旧资源、异常安全。默认实现逐成员赋值。"
  },
  {
    "instruction": "C++ 中什么是虚析构函数?",
    "input": "",
    "output": "基类析构函数声明为 virtual,确保通过基类指针删除派生类对象时调用派生类析构函数。管理多态资源时必须使用,否则派生类析构不执行。"
  },
  {
    "instruction": "C++ 中什么是静态多态?",
    "input": "",
    "output": "编译期确定调用目标,通过模板和函数重载实现。无虚函数开销,但不能处理运行时类型变化。CRTP 是常见的静态多态模式。"
  },
  {
    "instruction": "C++ 中什么是 CRTP?",
    "input": "",
    "output": "奇异递归模板模式(Curiously Recurring Template Pattern),派生类将自身作为基类模板参数:class Derived : public Base<Derived>。实现静态多态和代码复用,无虚函数开销。"
  },
  {
    "instruction": "C++ 中什么是接口类?",
    "input": "",
    "output": "C++ 没有 interface 关键字,通过只含纯虚函数且无数据成员的类模拟接口。也叫协议类,定义行为契约,派生类实现具体行为。"
  },
  {
    "instruction": "C++ 中什么是混入类(Mixin)?",
    "input": "",
    "output": "通过模板或继承向类注入功能的类。如 template<typename T> class Cloneable { T* clone() const { return new T(static_cast<T&>(*this)); } }。"
  },
  {
    "instruction": "C++ 中什么是 Pimpl 惯用法?",
    "input": "",
    "output": "Pointer to Implementation,将类的私有成员和实现细节移到单独的实现类中,原类只持有指针。减少头文件依赖、加速编译、稳定 ABI。"
  },
  {
    "instruction": "C++ 中什么是 NVI 惯用法?",
    "input": "",
    "output": "Non-Virtual Interface,公有非虚函数调用保护虚函数。非虚函数定义接口和不变式,虚函数提供定制点。模板方法模式的 C++ 实现。"
  },
  {
    "instruction": "C++ 中什么是对象切片?",
    "input": "",
    "output": "将派生类对象按值赋给基类变量时,派生类特有部分被截断,只保留基类子对象。通过引用或指针避免切片,这是多态使用引用/指针的原因之一。"
  },
  {
    "instruction": "C++ 中多重继承有什么问题?",
    "input": "",
    "output": "歧义(多个基类有同名成员)、菱形继承(基类子对象重复)、复杂度增加。用虚继承和限定名解决,优先使用组合或单继承+接口。"
  },
  {
    "instruction": "C++ 中什么是虚基类?",
    "input": "",
    "output": "被虚继承的基类。虚基类子对象在最远派生类中只存在一份,由最远派生类负责初始化。通过虚基类表或偏移访问。"
  },
  {
    "instruction": "C++ 中访问说明符有哪些?",
    "input": "",
    "output": "public(任何代码可访问)、protected(类及派生类可访问)、private(仅类自身和友元可访问)。控制成员的可见性和封装程度。"
  },
  {
    "instruction": "C++ 中什么是友元?",
    "input": "",
    "output": "friend 声明允许外部函数或类访问私有成员。友元不是成员,不受访问控制约束。破坏封装但有时必要,如运算符重载和工厂模式。"
  },
  {
    "instruction": "C++ 中友元可以继承吗?",
    "input": "",
    "output": "不可以。友元关系不可继承,基类的友元不能访问派生类的私有成员。同样,派生类的友元也不能访问基类的私有成员。"
  },
  {
    "instruction": "C++ 中什么是运算符重载?",
    "input": "",
    "output": "为自定义类型重新定义运算符行为。如 operator+ 实现自定义加法。不可改变运算符优先级、结合性和操作数数量,不可发明新运算符。"
  },
  {
    "instruction": "C++ 中哪些运算符不能重载?",
    "input": "",
    "output": "不能重载:. .* :: ?: sizeof typeid 和所有预处理运算符。这些运算符语义对语言至关重要,重载会破坏基本语义。"
  },
  {
    "instruction": "C++ 中什么是转换运算符?",
    "input": "",
    "output": "operator T() 定义从类类型到 T 的隐式转换。C++11 起可用 explicit operator bool() 避免意外转换,替代 safe bool 惯用法。"
  },
  {
    "instruction": "C++ 中什么是聚合初始化?",
    "input": "",
    "output": "对聚合类型用花括号初始化所有成员。C++11 起支持窄化检查,C++20 支持指定初始化器。如 Point{1, 2}。"
  },
  {
    "instruction": "C++ 中什么是委托与继承构造的选择?",
    "input": "",
    "output": "同类共享初始化逻辑用委托构造;派生类复用基类初始化用继承构造。两者不可同时出现在同一构造函数中。"
  },
  {
    "instruction": "C++ 中什么是空类?",
    "input": "",
    "output": "没有成员的类大小为 1 字节,C++ 要求每个对象有唯一地址。空类可有类型信息(虚函数)、静态成员、嵌套类型等。"
  },
  {
    "instruction": "C++ 中类的大小如何计算?",
    "input": "",
    "output": "非静态成员大小之和 + 对齐填充 + 虚指针(如有)。空类 1 字节,虚函数加 vptr(通常 8 字节),对齐影响最终大小。"
  },
  {
    "instruction": "C++ 中什么是内联函数?",
    "input": "",
    "output": "inline 建议编译器在调用处展开函数体。现代 C++ 中 inline 主要允许头文件多定义而不违反 ODR。编译器自行决定是否内联。"
  },
  {
    "instruction": "C++ 中成员函数的 const 修饰有什么用?",
    "input": "",
    "output": "const 成员函数承诺不修改对象状态(mutable 成员除外)。const 对象只能调用 const 成员函数,实现逻辑常量性。"
  },
  {
    "instruction": "C++ 中什么是 mutable 成员?",
    "input": "",
    "output": "mutable 修饰的成员变量可在 const 成员函数中修改。用于逻辑上不影响对象状态的缓存、延迟计算等场景。"
  },
  {
    "instruction": "C++ 中什么是静态成员变量?",
    "input": "",
    "output": "属于类而非实例的变量,所有对象共享一份。类内声明,类外定义(C++17 内联变量除外)。可通过类名直接访问。"
  },
  {
    "instruction": "C++ 中什么是静态成员函数?",
    "input": "",
    "output": "属于类而非实例的函数,无 this 指针。只能访问静态成员,不能声明为 const/virtual。通过类名调用。"
  },
  {
    "instruction": "C++ 中 this 指针是什么?",
    "input": "",
    "output": "this 是指向当前对象的隐式常量指针。在非静态成员函数中可用,类型为 T* const(非 const 方法)或 const T* const(const 方法)。"
  },
  {
    "instruction": "C++ 中什么是显式对象参数(deducing this)?",
    "input": "",
    "output": "C++23 引入,成员函数第一个参数为 this auto&& 或显式对象类型,推导对象的值类别。简化 const/非 const 重载和值类别转发。"
  },
  {
    "instruction": "C++ 中什么是虚函数的默认参数?",
    "input": "",
    "output": "虚函数的默认参数由静态类型决定,而非动态类型。调用时使用指针/引用的静态类型对应的默认参数值,容易出错,应避免在虚函数中使用默认参数。"
  },
  {
    "instruction": "C++ 中什么是协变返回类型?",
    "input": "",
    "output": "虚函数覆盖时返回类型可以是基类返回类型的派生类指针/引用。如 Base* f() 被覆盖为 Derived* f(),合法且类型安全。"
  },
  {
    "instruction": "C++ 中什么是纯虚函数的定义?",
    "input": "",
    "output": "纯虚函数可以有定义,但只能在类外提供。派生类可调用 Base::f()。用于提供默认行为同时强制派生类显式选择是否使用。"
  },
  {
    "instruction": "C++ 中什么是 protected 继承?",
    "input": "",
    "output": "protected 继承将基类 public 成员降为 protected。比 private 继承宽松,允许派生类访问基类成员。实践中很少使用。"
  },
  {
    "instruction": "C++ 中什么是 private 继承?",
    "input": "",
    "output": "private 继承将基类所有成员变为 private,表示'依据某物实现'而非'是某物'。通常组合更优,但 private 继承可访问基类保护成员和利用 EBO。"
  },
  {
    "instruction": "C++ 中继承和组合如何选择?",
    "input": "",
    "output": "优先使用组合:has-a 关系用组合,is-a 关系用继承。组合更灵活、低耦合。private 继承用于需要访问保护成员或 EBO 的场景。"
  },
  {
    "instruction": "C++ 中什么是 SFINAE?",
    "input": "",
    "output": "替换失败不是错误(Substitution Failure Is Not An Error)。模板参数替换失败时不报错,仅从重载集中移除该候选。用于条件启用模板特化。"
  },
  {
    "instruction": "C++ 中什么是类型特征(type traits)?",
    "input": "",
    "output": "<type_traits> 提供编译期类型查询和变换工具。如 is_integral_v<T>、remove_reference_t<T>。用于模板元编程和编译期条件逻辑。"
  },
  {
    "instruction": "C++ 中 enable_if 有什么用?",
    "input": "",
    "output": "SFINAE 的常用工具,条件启用模板。enable_if_t<cond, T> 在 cond 为 true 时定义类型 T,否则替换失败。用于约束模板实例化。"
  },
  {
    "instruction": "C++ 中什么是标签分发?",
    "input": "",
    "output": "用重载函数和标签类型在编译期选择不同实现。如 dispatch(true_type, args) 和 dispatch(false_type, args),根据类型特征选择。"
  },
  {
    "instruction": "C++ 中什么是空基类优化?",
    "input": "",
    "output": "空类作为基类时可不占空间(0字节),独立空类对象必须占 1 字节。EBO 在多重继承中减少空基类子对象的空间浪费。"
  },
  {
    "instruction": "C++ 中什么是 RAII 代理类?",
    "input": "",
    "output": "RAII 包装器管理资源生命周期。如 lock_guard 管理 mutex、unique_ptr 管理内存、fstream 管理文件。构造获取资源,析构释放资源。"
  },
  {
    "instruction": "C++ 中什么是 scope guard?",
    "input": "",
    "output": "通用 RAII 守卫,在作用域退出时执行指定操作。如 SCOPE_EXIT{ cleanup(); }; 无论正常退出还是异常都会执行清理。"
  },
  {
    "instruction": "C++ 中什么是值语义和引用语义?",
    "input": "",
    "output": "值语义:对象独立拥有数据,拷贝产生独立副本(C++ 默认);引用语义:对象共享数据,拷贝共享同一数据(Java 默认)。智能指针可实现引用语义。"
  },
  {
    "instruction": "C++ 中什么是深拷贝与浅拷贝的选择?",
    "input": "",
    "output": "含原始指针的类必须选择:深拷贝(独立副本,安全但慢)、浅拷贝(共享数据,快但需同步释放)、禁用拷贝(用 unique_ptr)。"
  },
  {
    "instruction": "C++ 中什么是不可变类?",
    "input": "",
    "output": "所有成员 const 且无修改状态的方法。通过构造函数初始化所有数据,返回新对象而非修改当前对象。线程安全但可能性能较差。"
  },
  {
    "instruction": "C++ 中什么是建造者模式?",
    "input": "",
    "output": "将复杂对象的构造过程与表示分离。链式调用如 Builder().setName(x).setAge(y).build()。解决构造函数参数过多的问题。"
  },
  {
    "instruction": "C++ 中什么是工厂模式?",
    "input": "",
    "output": "定义创建对象的接口,让子类决定实例化哪个类。用虚函数或模板方法延迟实例化决策,降低耦合。"
  },
  {
    "instruction": "C++ 中什么是观察者模式?",
    "input": "",
    "output": "主题对象状态变化时通知所有注册的观察者。用回调函数或虚函数实现。需注意观察者的生命周期管理和循环引用。"
  },
  {
    "instruction": "C++ 中什么是策略模式?",
    "input": "",
    "output": "将算法封装为可互换的策略对象,通过组合而非继承切换行为。用 std::function 或模板参数化策略。"
  },
  {
    "instruction": "C++ 中什么是单例模式?",
    "input": "",
    "output": "确保类只有一个实例。C++11 起局部静态变量线程安全:static T& instance() { static T inst; return inst; }。注意避免全局状态滥用。"
  },
  {
    "instruction": "C++ 中什么是类型擦除?",
    "input": "",
    "output": "隐藏对象的具体类型,通过统一接口操作。如 std::function 擦除可调用对象类型,std::any 擦除任意类型。运行时多态无需继承。"
  },
  {
    "instruction": "C++ 中什么是小对象优化?",
    "input": "",
    "output": "在对象内部存储小数据,避免堆分配。如 std::function 存储小可调用对象在内部缓冲区,std::string 的 SSO。"
  },
  {
    "instruction": "C++ 中什么是表达式模板?",
    "input": "",
    "output": "模板技术,延迟表达式求值,避免临时对象。如 D = A + B + C 不产生中间矩阵,而是生成一个复合表达式模板对象,最终一次遍历计算。"
  },
  {
    "instruction": "C++ 中什么是策略注入?",
    "input": "",
    "output": "通过模板参数注入策略类,编译期确定行为。如 std::vector<T, Allocator> 注入分配策略,std::sort 比较器注入排序策略。"
  },
  {
    "instruction": "C++ 中什么是依赖注入?",
    "input": "",
    "output": "将依赖从类内部创建改为外部传入。通过构造函数参数、setter 或模板参数注入。提高可测试性和灵活性。"
  },
  {
    "instruction": "C++ 中什么是空指针模式?",
    "input": "",
    "output": "提供'什么也不做'的默认实现,避免空指针检查。如 NullLogger::log() 什么都不做,客户端无需判断 logger 是否为空。"
  },
  {
    "instruction": "C++ 中什么是访问者模式?",
    "input": "",
    "output": "在不修改类层次的情况下添加新操作。通过双分派实现:accept 调用 visitor 的 visit(this),visitor 处理不同类型。"
  },
  {
    "instruction": "C++ 中 std::variant 和虚函数如何选择?",
    "input": "",
    "output": "std::variant 适合封闭类型集、值语义、编译期已知所有类型;虚函数适合开放类型集、引用语义、运行时扩展。variant 无堆分配和虚函数开销。"
  },
  {
    "instruction": "C++ 中什么是值对象?",
    "input": "",
    "output": "通过值而非身份区分的对象,相等性由属性决定。如 Date、Money。应不可变、可拷贝、支持相等比较。"
  },
  {
    "instruction": "C++ 中什么是实体对象?",
    "input": "",
    "output": "通过身份而非属性区分的对象,如 User、Order。有唯一标识,可变状态,比较身份而非属性。"
  },
  {
    "instruction": "C++ 中什么是 ADL 友元注入?",
    "input": "",
    "output": "通过友元函数定义在类内,ADL 可找到该函数。如 operator<< 定义为友元,ADL 在参数类型的命名空间中找到它。"
  },
  {
    "instruction": "C++ 中什么是 EBO 在标准库中的应用?",
    "input": "",
    "output": "std::allocator 是空类,通过 EBO 作为基类时不占空间,减少容器对象大小。std::pair 对空基类也利用 EBO。"
  },
  {
    "instruction": "C++ 中什么是虚函数的纯虚析构函数?",
    "input": "",
    "output": "纯虚析构函数使类成为抽象类,但必须提供定义(因为派生类析构时会调用)。如 virtual ~Base() = 0; Base::~Base() {}。"
  },
  {
    "instruction": "C++ 中什么是函数模板?",
    "input": "",
    "output": "函数模板用类型参数定义通用函数。如 template<typename T> T max(T a, T b)。编译器根据调用参数推导类型,生成特化版本。"
  },
  {
    "instruction": "C++ 中什么是类模板?",
    "input": "",
    "output": "类模板用类型参数定义通用类。如 template<typename T> class Stack。使用时必须指定类型参数 Stack<int>,编译器生成特化类。"
  },
  {
    "instruction": "C++ 中什么是模板特化?",
    "input": "",
    "output": "为特定类型提供专门实现。全特化:template<> void f<int>(int);偏特化:template<typename T> void f<T*>(T*)。特化版本优先于通用版本。"
  },
  {
    "instruction": "C++ 中什么是模板偏特化?",
    "input": "",
    "output": "对部分模板参数特化。如 template<typename T> class Vector<T*> 为指针类型提供特殊实现。只有类模板支持偏特化,函数模板不支持。"
  },
  {
    "instruction": "C++ 中 typename 和 class 有什么区别?",
    "input": "",
    "output": "在模板参数声明中完全等价。但 typename 还用于指示依赖类型名:typename T::iterator 中 typename 告诉编译器 iterator 是类型而非静态成员。"
  },
  {
    "instruction": "C++ 中什么是依赖类型?",
    "input": "",
    "output": "依赖于模板参数的类型,如 T::value_type。编译器无法在定义时确定其性质,需用 typename 前缀指示其为类型。"
  },
  {
    "instruction": "C++ 中什么是非类型模板参数?",
    "input": "",
    "output": "模板参数可以是编译期常量值,如 template<int N> struct Array { T data[N]; }。C++20 起允许浮点数和类类型非类型参数。"
  },
  {
    "instruction": "C++ 中什么是模板模板参数?",
    "input": "",
    "output": "模板参数本身是模板,如 template<template<typename> class Container> class Wrapper。允许策略化容器选择,如 Wrapper<vector>。"
  },
  {
    "instruction": "C++ 中什么是变参模板?",
    "input": "",
    "output": "template<typename... Args> 允许任意数量类型参数。Args 是类型参数包,用 sizeof...(Args) 获取数量,递归实例化或折叠表达式展开。"
  },
  {
    "instruction": "C++ 中什么是参数包展开?",
    "input": "",
    "output": "将参数包 Args... 展开为逗号分隔的各参数。展开位置:函数参数列表、模板参数列表、初始化列表、基类列表等。折叠表达式是 C++17 的简化展开方式。"
  },
  {
    "instruction": "C++ 中什么是 SFINAE?",
    "input": "",
    "output": "替换失败不是错误。模板参数替换导致类型错误时不报错,仅从重载集中移除。用于条件启用/禁用模板,enable_if 是典型应用。"
  },
  {
    "instruction": "C++ 中 enable_if 如何使用?",
    "input": "",
    "output": "template<typename T, typename = enable_if_t<is_integral_v<T>>> void f(T)。条件为 true 时函数参与重载,否则替换失败。可用于返回类型、模板参数或函数参数。"
  },
  {
    "instruction": "C++ 中什么是概念(Concepts)?",
    "input": "",
    "output": "C++20 引入的命名约束,对模板参数的语义要求。如 template<std::integral T> 限制 T 为整数。比 SFINAE 更清晰,错误信息更友好。"
  },
  {
    "instruction": "C++ 中如何定义自定义概念?",
    "input": "",
    "output": "template<typename T> concept Addable = requires(T a, T b) { a + b; }; 用 requires 表达式定义约束。可组合:concept Number = Integral<T> || FloatingPoint<T>。"
  },
  {
    "instruction": "C++ 中 requires 子句和 requires 表达式有什么区别?",
    "input": "",
    "output": "requires 子句约束模板:template<typename T> requires Concept<T> void f(T);requires 表达式定义约束:requires(T a) { a + b; } 求值为 bool。"
  },
  {
    "instruction": "C++ 中什么是约束的部分排序?",
    "input": "",
    "output": "C++20 中更具体的约束优先。如 Integral<T> 比 Numeric<T> 更具体,重载决议选择更受约束的版本。替代 SFINAE 的复杂优先级规则。"
  },
  {
    "instruction": "C++ 中什么是 CTAD?",
    "input": "",
    "output": "类模板参数推导(Class Template Argument Deduction),C++17 引入。如 vector v{1,2,3} 推导为 vector<int>,pair p{1, 2.0} 推导为 pair<int, double>。"
  },
  {
    "instruction": "C++ 中什么是推导指引?",
    "input": "",
    "output": "自定义 CTAD 行为的语法。如 template<typename Iter> Vector(Iter, Iter) -> Vector<typename iterator_traits<Iter>::value_type>。指导编译器如何推导模板参数。"
  },
  {
    "instruction": "C++ 中什么是别名模板?",
    "input": "",
    "output": "template<typename T> using Vec = vector<T, MyAlloc<T>>。为模板创建别名,typedef 不支持模板别名。C++11 引入。"
  },
  {
    "instruction": "C++ 中什么是变量模板?",
    "input": "",
    "output": "C++14 引入,template<typename T> constexpr T pi = T(3.14159265358979)。为不同类型提供常量值,如 pi<float> 和 pi<double>。"
  },
  {
    "instruction": "C++ 中什么是内联变量?",
    "input": "",
    "output": "C++17 引入 inline 修饰变量定义。允许头文件中定义变量不违反 ODR,所有翻译单元共享同一实例。类静态成员变量可 inline 定义。"
  },
  {
    "instruction": "C++ 中模板的实例化时机是什么?",
    "input": "",
    "output": "隐式实例化:使用时编译器生成代码;显式实例化:template class vector<int> 强制生成。声明 extern template class vector<int> 阻止隐式实例化。"
  },
  {
    "instruction": "C++ 中什么是显式实例化?",
    "input": "",
    "output": "template class MyClass<int>; 或 template void f<int>(int); 强制编译器生成特定特化的代码。用于减少编译时间或控制代码生成位置。"
  },
  {
    "instruction": "C++ 中什么是 extern 模板?",
    "input": "",
    "output": "extern template class vector<int>; 阻止编译器在本翻译单元实例化该特化,使用其他翻译单元中的实例化。减少重复实例化开销。"
  },
  {
    "instruction": "C++ 中模板代码膨胀怎么解决?",
    "input": "",
    "output": "模板为每种类型生成代码,导致二进制膨胀。解决方案:将类型无关代码提取到非模板基类;使用 void* 实现通用逻辑;显式实例化常用类型。"
  },
  {
    "instruction": "C++ 中什么是编译期计算?",
    "input": "",
    "output": "使用模板和 constexpr 在编译期执行计算。如模板递归计算阶乘、constexpr 函数。编译期计算无运行时开销,但增加编译时间。"
  },
  {
    "instruction": "C++ 中 constexpr 函数有什么限制?",
    "input": "",
    "output": "C++11:只能有一条 return 语句;C++14:允许局部变量、if/for 等;C++23:几乎无限制。constexpr 函数可在编译期或运行期执行。"
  },
  {
    "instruction": "C++ 中 consteval 和 constexpr 有什么区别?",
    "input": "",
    "output": "constexpr 函数可在编译期或运行期执行;consteval(C++20)函数必须编译期执行,称为立即函数。consteval 保证编译期求值。"
  },
  {
    "instruction": "C++ 中什么是编译期字符串处理?",
    "input": "",
    "output": "利用模板和 constexpr 处理字符串。C++20 起字符串字面量可作为模板参数,consteval 函数可操作字符串。实现编译期哈希、正则等。"
  },
  {
    "instruction": "C++ 中什么是静态断言?",
    "input": "",
    "output": "static_assert(常量表达式, 消息) 在编译期检查条件,失败则编译错误。用于模板约束和编译期验证,C++17 起消息可省略。"
  },
  {
    "instruction": "C++ 中什么是类型列表?",
    "input": "",
    "output": "模板元编程中存储类型序列的技术,如 template<typename... Ts> struct TypeList。可递归遍历、查询、变换,是模板元编程的基础数据结构。"
  },
  {
    "instruction": "C++ 中什么是编译期 if?",
    "input": "",
    "output": "if constexpr (cond) 在编译期判断条件,false 分支不实例化。替代 SFINAE 和标签分发,简化模板代码。C++17 引入。"
  },
  {
    "instruction": "C++ 中什么是折叠表达式?",
    "input": "",
    "output": "C++17 引入,简化参数包展开。(args + ...) 右折叠,(... + args) 左折叠。支持 +、*、&&、||、, 等运算符。如 (print(args), ...) 依次打印。"
  },
  {
    "instruction": "C++ 中什么是完美返回?",
    "input": "",
    "output": "decltype(auto) 配合 return 语句保留返回值的值类别。如 decltype(auto) f() { return x; } 返回引用,auto f() 返回值。"
  },
  {
    "instruction": "C++ 中什么是尾置返回类型?",
    "input": "",
    "output": "auto f(int x) -> int 声明返回类型在参数列表之后。用于返回类型依赖参数的场景,如 auto f(T t) -> decltype(t.foo()) 。"
  },
  {
    "instruction": "C++ 中什么是返回类型推导?",
    "input": "",
    "output": "C++14 起 auto f() { return expr; } 让编译器推导返回类型。decltype(auto) 保留引用性。不能用于虚函数和未解析的递归调用。"
  },
  {
    "instruction": "C++ 中模板和虚函数如何选择?",
    "input": "",
    "output": "模板:编译期多态,零开销,类型安全,代码膨胀;虚函数:运行期多态,有虚调用开销,类型擦除,无膨胀。根据是否需要运行期灵活性选择。"
  },
  {
    "instruction": "C++ 中什么是策略类?",
    "input": "",
    "output": "通过模板参数注入行为的类。如 template<typename Alloc> class vector。策略类通常为空类,利用 EBO 不占空间。"
  },
  {
    "instruction": "C++ 中什么是标签类型?",
    "input": "",
    "output": "空结构体用于编译期类型区分。如 struct input_iterator_tag {}。通过重载选择不同实现,如 advance(it, n, iterator_category)。"
  },
  {
    "instruction": "C++ 中什么是编译期整数序列?",
    "input": "",
    "output": "std::integer_sequence<int, 0,1,2,3> 和辅助 std::make_index_sequence<N>。用于在编译期展开参数包,如将 tuple 展开为函数参数。"
  },
  {
    "instruction": "C++ 中什么是 std::tuple?",
    "input": "",
    "output": "固定大小的异构容器,如 tuple<int, string, double>。用 get<0>(t) 或 get<int>(t) 访问。支持结构化绑定 auto [a,b,c] = t。"
  },
  {
    "instruction": "C++ 中什么是 std::apply?",
    "input": "",
    "output": "C++17 引入,将 tuple 展开为函数参数。如 apply(f, make_tuple(1, 2.0, \"hi\")) 等价于 f(1, 2.0, \"hi\")。"
  },
  {
    "instruction": "C++ 中模板友元有什么规则?",
    "input": "",
    "output": "一模板类的友元可以是:非模板函数、模板函数的特定特化、模板函数的所有特化。友元声明需精确匹配,否则无法访问私有成员。"
  },
  {
    "instruction": "C++ 中什么是注入类名?",
    "input": "",
    "output": "在类模板的作用域内,类名可指代当前实例化。如 template<typename T> class A { A* p; } 中 A 等价于 A<T>。简化类内自引用。"
  },
  {
    "instruction": "C++ 中什么是 ADL 与模板的交互?",
    "input": "",
    "output": "模板中调用依赖名称时通过 ADL 查找。如 std::sort(v.begin(), v.end()) 中的 swap 通过 ADL 找到自定义 swap。"
  },
  {
    "instruction": "C++ 中什么是两阶段名称查找?",
    "input": "",
    "output": "模板定义时查找非依赖名称,实例化时查找依赖名称。非依赖名称在定义时绑定,依赖名称在实例化时通过 ADL 查找。"
  },
  {
    "instruction": "C++ 中什么是模板的显式特化?",
    "input": "",
    "output": "template<> 为特定参数组合提供完全不同的实现。如 template<> void f<int>(int x) { 专门处理int }。全特化不参与重载决议。"
  },
  {
    "instruction": "C++ 中什么是部分特化的偏序?",
    "input": "",
    "output": "多个偏特化匹配时,编译器选择更特化的版本。如 T* 比 T 更特化,const T 比 T 更特化。无法确定时编译错误。"
  },
  {
    "instruction": "C++ 中什么是子stitution failure?",
    "input": "",
    "output": "模板参数替换时类型不合法,如 void* 不能做算术。SFINAE 规则使这种失败不报错,仅从候选集中移除。"
  },
  {
    "instruction": "C++ 中什么是 std::declval?",
    "input": "",
    "output": "declval<T>() 在不求值上下文中获取 T 的引用,无需默认构造函数。如 decltype(std::declval<T>().foo()) 获取返回类型。"
  },
  {
    "instruction": "C++ 中什么是 std::void_t?",
    "input": "",
    "output": "C++17 引入,template<typename...> using void_t = void。用于 SFINAE 检测类型特征:若替换失败则特化被排除。"
  },
  {
    "instruction": "C++ 中什么是概念的四种子句形式?",
    "input": "",
    "output": "1. requires Concept<T>;2. Concept<T> 紧跟模板参数;3. requires { 表达式 };4. requires (参数) { 表达式 }。四种写法等价。"
  },
  {
    "instruction": "C++ 中 vector 和 list 有什么区别?",
    "input": "",
    "output": "vector 连续内存,随机访问 O(1),插入删除尾部 O(1) 中间 O(n);list 双向链表,随机访问 O(n),任意位置插入删除 O(1)。优先用 vector,缓存友好。"
  },
  {
    "instruction": "C++ 中 vector 和 deque 有什么区别?",
    "input": "",
    "output": "vector 单块连续内存;deque 分段连续,头尾插入 O(1)。deque 无需重分配整个容器但迭代器更复杂。频繁头插用 deque,否则用 vector。"
  },
  {
    "instruction": "C++ 中 map 和 unordered_map 有什么区别?",
    "input": "",
    "output": "map 基于红黑树,有序,查找 O(log n);unordered_map 基于哈希表,无序,平均 O(1)。需要有序遍历或范围查询用 map,只需查找用 unordered_map。"
  },
  {
    "instruction": "C++ 中 set 和 unordered_set 有什么区别?",
    "input": "",
    "output": "set 红黑树,有序,查找 O(log n);unordered_set 哈希表,无序,平均 O(1)。需要有序或范围查询用 set,只需成员检测用 unordered_set。"
  },
  {
    "instruction": "C++ 中什么是迭代器?",
    "input": "",
    "output": "迭代器是访问容器元素的通用接口,类似指针。分为输入、输出、前向、双向、随机访问迭代器(C++20 新增连续迭代器)。算法通过迭代器操作容器。"
  },
  {
    "instruction": "C++ 中迭代器失效有什么规则?",
    "input": "",
    "output": "vector:插入可能全部失效,删除只影响之后;list:只有被删除元素失效;map:只有被删除元素失效。操作容器后需重新获取迭代器。"
  },
  {
    "instruction": "C++ 中什么是范围 for 循环?",
    "input": "",
    "output": "C++11 引入 for (auto& x : container) 遍历容器。等价于用 begin()/end() 迭代器循环。不能在循环中修改容器结构。"
  },
  {
    "instruction": "C++ 中 std::array 和数组有什么区别?",
    "input": "",
    "output": "std::array 是固定大小容器的包装,支持迭代器、size()、at() 边界检查、结构化绑定。比 C 数组更安全,零开销抽象。"
  },
  {
    "instruction": "C++ 中 std::string 有什么优化?",
    "input": "",
    "output": "SSO(小字符串优化)通常 15-22 字节内不分配堆;C++11 起支持移动语义;C++17 std::string_view 避免拷贝;C++23 改进字符串处理。"
  },
  {
    "instruction": "C++ 中什么是 string_view?",
    "input": "",
    "output": "C++17 引入,非拥有的字符串引用。不拷贝数据,只存储指针和长度。用于函数参数避免 string 拷贝,注意不要持有临时字符串的 view。"
  },
  {
    "instruction": "C++ 中什么是 span?",
    "input": "",
    "output": "C++20 引入,非拥有的连续元素视图。如 span<int> s(vec.data(), vec.size())。类似 string_view 但用于任意类型,安全替代指针+长度。"
  },
  {
    "instruction": "C++ 中 std::sort 的时间复杂度?",
    "input": "",
    "output": "O(n log n),通常为内省排序(introsort):先快速排序,递归深度超限切换堆排序,小范围用插入排序。不稳定排序,需稳定用 stable_sort。"
  },
  {
    "instruction": "C++ 中什么是 STL 算法?",
    "input": "",
    "output": "<algorithm> 提供通用算法:排序(sort)、查找(find/binary_search)、修改(transform/copy)、集合(set_union)、堆(make_heap)等。配合迭代器使用。"
  },
  {
    "instruction": "C++ 中 std::find 和 std::binary_search 有什么区别?",
    "input": "",
    "output": "find 线性查找 O(n),不需要有序;binary_search 二分查找 O(log n),要求有序。binary_search 只返回 bool,需 lower_bound 获取位置。"
  },
  {
    "instruction": "C++ 中 std::transform 有什么用?",
    "input": "",
    "output": "对范围元素应用函数,结果写入目标范围。如 transform(v.begin(), v.end(), v.begin(), [](int x){ return x*2; }) 将元素翻倍。"
  },
  {
    "instruction": "C++ 中 std::accumulate 有什么用?",
    "input": "",
    "output": "累加范围元素,可自定义操作。如 accumulate(v.begin(), v.end(), 0) 求和;accumulate(v.begin(), v.end(), 1, multiplies) 求积。"
  },
  {
    "instruction": "C++ 中 std::remove 和 erase 有什么区别?",
    "input": "",
    "output": "remove 是算法,不删除元素只移动待保留元素到前面,返回新逻辑末尾;erase 是容器方法,真正删除元素。惯用法:v.erase(remove(v.begin(), v.end(), val), v.end())。"
  },
  {
    "instruction": "C++ 中什么是 erase-remove 惯用法?",
    "input": "",
    "output": "v.erase(std::remove(v.begin(), v.end(), value), v.end()) 真正删除所有等于 value 的元素。C++20 起可直接 std::erase(v, value)。"
  },
  {
    "instruction": "C++ 中 std::unique 有什么用?",
    "input": "",
    "output": "将连续重复元素移到末尾,返回新逻辑末尾。通常先 sort 再 unique,再 erase:v.erase(unique(v.begin(), v.end()), v.end())。C++20 起 std::unique_erase。"
  },
  {
    "instruction": "C++ 中 std::partition 有什么用?",
    "input": "",
    "output": "将范围按谓词分为两组,满足条件的在前。如 partition(v.begin(), v.end(), [](int x){ return x > 0; })。stable_partition 保持相对顺序。"
  },
  {
    "instruction": "C++ 中什么是优先队列?",
    "input": "",
    "output": "std::priority_queue 是适配器,默认最大堆。top() 返回最大元素,push() 插入,pop() 删除。可传比较器和底层容器自定义行为。"
  },
  {
    "instruction": "C++ 中什么是 std::stack?",
    "input": "",
    "output": "栈适配器,默认基于 deque。push() 入栈,pop() 出栈,top() 访问栈顶。LIFO 后进先出。"
  },
  {
    "instruction": "C++ 中什么是 std::queue?",
    "input": "",
    "output": "队列适配器,默认基于 deque。push() 入队,pop() 出队,front()/back() 访问。FIFO 先进先出。"
  },
  {
    "instruction": "C++ 中 multimap 和 map 有什么区别?",
    "input": "",
    "output": "multimap 允许重复键,map 键唯一。multimap 没有 operator[],用 equal_range() 获取同一键的所有值。"
  },
  {
    "instruction": "C++ 中 unordered_map 如何自定义键类型?",
    "input": "",
    "output": "需提供哈希函数和相等比较。如特化 hash<MyType> 或传自定义 Hash 和 KeyEqual 模板参数。哈希函数应均匀分布。"
  },
  {
    "instruction": "C++ 中 vector 的 reserve 和 resize 有什么区别?",
    "input": "",
    "output": "reserve(n) 预分配容量不改变 size,不构造元素;resize(n) 改变 size,新元素值初始化。reserve 避免重分配,resize 实际扩展元素。"
  },
  {
    "instruction": "C++ 中 vector 的 capacity 和 size 有什么区别?",
    "input": "",
    "output": "size 是当前元素数量;capacity 是已分配内存可容纳的元素数量。capacity >= size,push_back 在 capacity 不足时重分配。"
  },
  {
    "instruction": "C++ 中 vector 的 emplace_back 和 push_back 有什么区别?",
    "input": "",
    "output": "push_back 接受对象或右值;emplace_back 直接在容器内构造对象,参数转发给构造函数。emplace_back 避免临时对象,更高效。"
  },
  {
    "instruction": "C++ 中什么是 emplace?",
    "input": "",
    "output": "C++11 引入,在容器中直接构造元素而非拷贝/移动。如 m.emplace(key, arg1, arg2) 在 map 中直接构造 value。比 insert 减少一次构造。"
  },
  {
    "instruction": "C++ 中什么是移动迭代器?",
    "input": "",
    "output": "std::make_move_iterator 将普通迭代器转为移动迭代器,解引用时返回右值引用。如 vector<T> v2(make_move_iterator(v1.begin()), make_move_iterator(v1.end())) 移动而非拷贝。"
  },
  {
    "instruction": "C++ 中什么是反向迭代器?",
    "input": "",
    "output": "std::reverse_iterator 反向遍历容器,rbegin() 指向末尾,rend() 指向开头前。base() 获取对应的正向迭代器。"
  },
  {
    "instruction": "C++ 中什么是流迭代器?",
    "input": "",
    "output": "std::istream_iterator 从输入流读取;std::ostream_iterator 向输出流写入。如 copy(v.begin(), v.end(), ostream_iterator<int>(cout, \" \"))。"
  },
  {
    "instruction": "C++ 中什么是插入迭代器?",
    "input": "",
    "output": "back_inserter 创建 push_back 插入迭代器;front_inserter 创建 push_front 插入迭代器;inserter 创建 insert 插入迭代器。用于算法写入容器。"
  },
  {
    "instruction": "C++ 中 std::lower_bound 和 upper_bound 有什么区别?",
    "input": "",
    "output": "lower_bound 返回第一个 >= 值的位置;upper_bound 返回第一个 > 值的位置。两者之差为等于值的元素数量。要求有序范围。"
  },
  {
    "instruction": "C++ 中 std::equal_range 有什么用?",
    "input": "",
    "output": "返回 [lower_bound, upper_bound) 迭代器对,即所有等于值的子范围。用于有序范围中查找等值区间。"
  },
  {
    "instruction": "C++ 中 std::merge 有什么用?",
    "input": "",
    "output": "合并两个有序范围为一个新的有序范围。如 merge(a.begin(), a.end(), b.begin(), b.end(), back_inserter(c))。稳定排序。"
  },
  {
    "instruction": "C++ 中 std::nth_element 有什么用?",
    "input": "",
    "output": "将第 n 个位置的元素放到正确位置,左边都 <= 它,右边都 >= 它。O(n) 平均复杂度,用于找中位数或第 k 大。"
  },
  {
    "instruction": "C++ 中 std::partial_sort 有什么用?",
    "input": "",
    "output": "对范围前 m 个元素排序,其余不保证顺序。如 partial_sort(v.begin(), v.begin()+10, v.end()) 找最小的 10 个并排序。O(n log m)。"
  },
  {
    "instruction": "C++ 中什么是 std::numeric_limits?",
    "input": "",
    "output": "<limits> 提供类型数值属性:min()、max()、lowest()、epsilon()、is_integer、digits 等。替代 C 的 INT_MAX 等宏,类型安全。"
  },
  {
    "instruction": "C++ 中什么是 std::function?",
    "input": "",
    "output": "通用的可调用对象包装器,可存储函数指针、lambda、仿函数、bind 表达式。如 function<int(int,int)> f = [](int a,int b){return a+b;}; 有类型擦除开销。"
  },
  {
    "instruction": "C++ 中什么是 std::bind?",
    "input": "",
    "output": "C++11 绑定函数参数,生成新的可调用对象。如 auto f = bind(func, _1, 42) 固定第二参数为 42。现代 C++ 推荐用 lambda 替代 bind。"
  },
  {
    "instruction": "C++ 中什么是仿函数?",
    "input": "",
    "output": "重载 operator() 的类,可像函数一样调用。如 struct Greater { bool operator()(int a, int b) { return a > b; } }; 比函数指针更灵活,可有状态。"
  },
  {
    "instruction": "C++ 中什么是 Ranges 库?",
    "input": "",
    "output": "C++20 引入 <ranges>,提供组合式惰性操作。如 views::filter | views::transform 管道风格。不立即求值,遍历时才计算,更优雅高效。"
  },
  {
    "instruction": "C++ 中什么是视图(View)?",
    "input": "",
    "output": "C++20 Ranges 中的轻量非拥有范围。如 filter_view、transform_view 不拷贝数据,组合时无开销。可赋值给 auto 变量延迟求值。"
  },
  {
    "instruction": "C++ 中 std::any_of、std::all_of、std::none_of 有什么用?",
    "input": "",
    "output": "范围算法:any_of 任一元素满足谓词;all_of 全部满足;none_of 全不满足。替代手写循环,语义更清晰。"
  },
  {
    "instruction": "C++ 中 std::count 和 std::count_if 有什么区别?",
    "input": "",
    "output": "count 统计等于指定值的元素数;count_if 统计满足谓词的元素数。如 count_if(v.begin(), v.end(), [](int x){return x > 0;})。"
  },
  {
    "instruction": "C++ 中 std::for_each 有什么用?",
    "input": "",
    "output": "对范围每个元素应用函数。如 for_each(v.begin(), v.end(), [](int& x){ x *= 2; })。函数可带状态(仿函数)。范围 for 更常用,但 for_each 可返回函数对象。"
  },
  {
    "instruction": "C++ 中 std::generate 有什么用?",
    "input": "",
    "output": "用生成器填充范围。如 generate(v.begin(), v.end(), rand) 用随机数填充。iota 生成递增序列。"
  },
  {
    "instruction": "C++ 中 std::shuffle 有什么用?",
    "input": "",
    "output": "随机打乱范围元素,替代 C 的 random_shuffle。需传入随机数引擎:shuffle(v.begin(), v.end(), rng)。C++11 引入。"
  },
  {
    "instruction": "C++ 中什么是 std::pair?",
    "input": "",
    "output": "存储两个异构值的容器,如 pair<int, string> p(1, \"hi\")。用 .first/.second 或结构化绑定访问。make_pair 自动推导类型。"
  },
  {
    "instruction": "C++ 中什么是 std::tuple?",
    "input": "",
    "output": "固定大小异构容器,如 tuple<int, string, double>。用 get<0>(t) 或 get<string>(t) 访问。支持结构化绑定和 tuple_cat 连接。"
  },
  {
    "instruction": "C++ 中什么是 std::optional?",
    "input": "",
    "output": "C++17 引入,表示可能为空的值。如 optional<int> f() 可能返回 int 或 nullopt。用 has_value() 检查,value() 或 * 访问。替代哨兵值。"
  },
  {
    "instruction": "C++ 中什么是 std::variant?",
    "input": "",
    "output": "C++17 引入,类型安全联合体。如 variant<int, string> v = \"hello\"。用 holds_alternative<int>(v) 检查,visit 访问。比 union 更安全。"
  },
  {
    "instruction": "C++ 中什么是 std::any?",
    "input": "",
    "output": "C++17 引入,可持有任意类型值。用 any_cast<T> 访问,类型不匹配抛 bad_any_cast。比 void* 安全但有运行时开销。"
  },
  {
    "instruction": "C++ 中什么是 std::filesystem?",
    "input": "",
    "output": "C++17 引入文件系统库。path 类表示路径,directory_iterator 遍历目录,copy/remove/rename 操作文件。跨平台替代 POSIX/Win32 API。"
  },
  {
    "instruction": "C++ 中什么是 std::chrono?",
    "input": "",
    "output": "C++11 时间库。duration 表示时间段,time_point 表示时间点,clock 提供时钟。C++20 增加日历和时区支持。"
  },
  {
    "instruction": "C++ 中什么是 std::regex?",
    "input": "",
    "output": "C++11 正则表达式库。regex 对象编译模式,smatch 存储匹配结果。支持 ECMAScript 和 POSIX 语法。性能通常不如专用正则库。"
  },
  {
    "instruction": "C++ 中什么是 std::locale?",
    "input": "",
    "output": "本地化支持,控制数字格式、日期格式、字符分类等。如 locale(\"zh_CN.UTF-8\")。cout.imbue(locale()) 影响输出格式。"
  },
  {
    "instruction": "C++ 中什么是 std::atomic?",
    "input": "",
    "output": "C++11 原子操作,保证读-改-写操作不可分割。如 atomic<int> x; x.fetch_add(1) 原子递增。支持各种内存序。"
  },
  {
    "instruction": "C++ 中什么是 std::thread?",
    "input": "",
    "output": "C++11 线程类。thread t(func, args) 创建线程,t.join() 等待完成,t.detach() 分离。必须 join 或 detach,否则析构时 terminate。"
  },
  {
    "instruction": "C++ 中什么是 std::future?",
    "input": "",
    "output": "C++11 异步结果。async 启动异步任务返回 future,future.get() 阻塞获取结果。shared_future 可多次 get。"
  },
  {
    "instruction": "C++ 中什么是 std::promise?",
    "input": "",
    "output": "C++11 异步提供者。promise.set_value() 设置结果,promise.get_future() 获取关联 future。用于线程间传值。"
  },
  {
    "instruction": "C++ 中什么是 std::async?",
    "input": "",
    "output": "C++11 异步任务启动器。async(launch::async, func, args) 在新线程执行;async(launch::deferred, ...) 延迟到 get() 时执行。默认策略由实现决定。"
  },
  {
    "instruction": "C++ 中什么是 std::mutex?",
    "input": "",
    "output": "C++11 互斥锁。lock() 加锁,unlock() 解锁。推荐用 lock_guard/unique_lock 管理,避免忘记解锁。不可递归加锁。"
  },
  {
    "instruction": "C++ 中什么是 std::condition_variable?",
    "input": "",
    "output": "C++11 条件变量,配合 mutex 实现等待-通知模式。wait() 释放锁并等待,notify_one()/notify_all() 唤醒等待线程。"
  },
  {
    "instruction": "C++ 中什么是 std::shared_mutex?",
    "input": "",
    "output": "C++17 读写锁。shared_lock 允许多读者并发;unique_lock 独占写。适合读多写少场景。C++14 有 std::shared_timed_mutex。"
  },
  {
    "instruction": "C++ 中什么是 std::call_once?",
    "input": "",
    "output": "C++11 保证函数只执行一次。once_flag 标记状态,call_once(flag, func) 首次调用执行 func,后续调用跳过。线程安全的延迟初始化。"
  },
  {
    "instruction": "C++ 中什么是线程局部存储?",
    "input": "",
    "output": "thread_local 修饰的变量每个线程有独立实例。如 thread_local int x; 每个线程的 x 互不影响。生命周期至线程结束。"
  },
  {
    "instruction": "C++ 中什么是 std::jthread?",
    "input": "",
    "output": "C++20 引入,自动 join 的线程类。析构时自动请求停止并等待。支持协作式取消:get_stop_source() 请求停止。"
  },
  {
    "instruction": "C++ 中什么是 std::latch 和 std::barrier?",
    "input": "",
    "output": "C++20 引入。latch 是一次性倒计时同步点;barrier 是可重用的阶段同步点。latch.count_down_and_wait() 等待计数归零;barrier.arrive_and_wait() 等待所有线程到达。"
  },
  {
    "instruction": "C++ 中什么是 std::atomic_ref?",
    "input": "",
    "output": "C++20 引入,对非原子对象的原子引用。如 atomic_ref<int> ref(x) 使普通 int 可原子操作。适用于无法修改对象类型但需要原子访问的场景。"
  },
  {
    "instruction": "C++ 中什么是 std::semaphore?",
    "input": "",
    "output": "C++20 引入信号量。counting_semaphore<N> 计数信号量,binary_semaphore 二值信号量。acquire() 减计数,release() 增计数。"
  },
  {
    "instruction": "C++ 中什么是内存序?",
    "input": "",
    "output": "std::atomic 操作的内存排序约束:memory_order_relaxed(无序)、acquire/release(获取/释放语义)、seq_cst(顺序一致,默认)。越严格开销越大。"
  },
  {
    "instruction": "C++ 中什么是自旋锁?",
    "input": "",
    "output": "忙等待锁,循环尝试获取。用 atomic_flag 实现:while (flag.test_and_set(memory_order_acquire)) {}。短临界区可能比 mutex 快,但浪费 CPU。"
  },
  {
    "instruction": "C++ 中什么是无锁编程?",
    "input": "",
    "output": "不使用锁实现线程安全。依赖原子操作和内存序。复杂且易错,需正确使用 acquire/release 语义。优先用 mutex,性能瓶颈时再考虑无锁。"
  },
  {
    "instruction": "C++ 中什么是线程池?",
    "input": "",
    "output": "预创建一组线程,任务队列分发工作。避免频繁创建销毁线程开销。C++ 标准未提供,需自行实现或用第三方库。"
  },
  {
    "instruction": "C++ 中什么是 std::packaged_task?",
    "input": "",
    "output": "C++11 将可调用对象包装为异步任务。packaged_task<int()> task(func); future<int> f = task.get_future(); task() 执行并设置结果。"
  },
  {
    "instruction": "C++ 中什么是 std::stop_source 和 std::stop_token?",
    "input": "",
    "output": "C++20 引入协作式取消机制。stop_source 请求停止,stop_token 检查是否停止。jthread 内置 stop_source,线程内定期检查 stop_token。"
  },
  {
    "instruction": "C++ 中什么是异常?",
    "input": "",
    "output": "异常是错误处理的机制,throw 抛出异常对象,try/catch 捕获处理。异常沿调用栈向上传播直到被捕获,未捕获异常调用 std::terminate。"
  },
  {
    "instruction": "C++ 中 throw 和 noexcept 有什么区别?",
    "input": "",
    "output": "throw 动态说明可能抛出的异常(C++17 废弃动态异常说明);noexcept 指定函数不抛异常,若抛出则 std::terminate。noexcept 是类型系统的一部分。"
  },
  {
    "instruction": "C++ 中什么是栈展开?",
    "input": "",
    "output": "异常抛出后,运行时从当前函数向外逐帧销毁局部对象(调用析构函数),直到找到匹配的 catch。析构函数不应抛异常,否则 std::terminate。"
  },
  {
    "instruction": "C++ 中异常安全有哪几个等级?",
    "input": "",
    "output": "1. 不抛保证(noexcept);2. 强保证(操作失败状态不变,commit-or-rollback);3. 基本保证(不变式保持,无泄漏);4. 无保证。"
  },
  {
    "instruction": "C++ 中如何实现强异常安全保证?",
    "input": "",
    "output": "先在临时副本上操作,成功后用 nothrow 操作(如 swap)提交。如 copy-and-swap 惯用法。确保操作要么完全成功要么完全回滚。"
  },
  {
    "instruction": "C++ 中什么是 RAII 与异常安全?",
    "input": "",
    "output": "RAII 是异常安全的基础。栈展开时自动调用析构函数释放资源,避免异常路径上的资源泄漏。所有资源管理都应使用 RAII。"
  },
  {
    "instruction": "C++ 中 catch(...) 有什么用?",
    "input": "",
    "output": "捕获所有类型的异常。常用于:记录日志后重新抛出、翻译异常类型、确保清理。catch(...) 块中可用 throw; 重新抛出当前异常。"
  },
  {
    "instruction": "C++ 中什么是异常重新抛出?",
    "input": "",
    "output": "catch 块中 throw; 重新抛出当前捕获的异常。保留原始异常类型和 what() 信息。不要用 throw e; 会切片为静态类型。"
  },
  {
    "instruction": "C++ 中什么是异常规格说明?",
    "input": "",
    "output": "C++11 前 throw(type) 指定可能抛出的类型;C++11 起 noexcept 替代。动态异常规格在 C++17 移除,noexcept(bool) 成为标准。"
  },
  {
    "instruction": "C++ 中 noexcept 有什么性能影响?",
    "input": "",
    "output": "noexcept 函数不参与栈展开,编译器可优化。标准容器如 vector::push_back 根据移动构造是否 noexcept 选择移动或拷贝。"
  },
  {
    "instruction": "C++ 中什么是异常与构造函数?",
    "input": "",
    "output": "构造函数抛异常时对象未完全构造,析构函数不会被调用。已构造的成员和基类子对象会正常析构。需手动清理构造函数中获取的非成员资源。"
  },
  {
    "instruction": "C++ 中什么是异常与析构函数?",
    "input": "",
    "output": "析构函数默认 noexcept。若析构函数可能抛异常,需显式声明 noexcept(false)。但强烈不建议,因为栈展开时析构抛异常会 std::terminate。"
  },
  {
    "instruction": "C++ 中什么是 std::exception 层次?",
    "input": "",
    "output": "标准异常基类 std::exception,派生 logic_error(编程错误)和 runtime_error(运行时错误)。常用派生:invalid_argument、out_of_range、bad_alloc、bad_cast 等。"
  },
  {
    "instruction": "C++ 中如何自定义异常类?",
    "input": "",
    "output": "继承 std::exception 或其派生类,重写 what() 返回错误描述。如 class MyError : public std::runtime_error { using runtime_error::runtime_error; };"
  },
  {
    "instruction": "C++ 中什么是异常与多线程?",
    "input": "",
    "output": "异常不能跨线程传播。线程中未捕获异常调用 std::terminate。用 future/promise 传递异常:线程中异常被捕获后存入 promise,future.get() 重新抛出。"
  },
  {
    "instruction": "C++ 中异常和错误码如何选择?",
    "input": "",
    "output": "异常:错误不常见、需跨层传播、需自动清理;错误码:错误常见、性能关键、实时系统。C++23 的 std::expected 是中间方案。"
  },
  {
    "instruction": "C++ 中什么是 std::expected?",
    "input": "",
    "output": "C++23 引入,返回值或错误。如 expected<int, Error> f() 返回值或 unexpected(err)。比异常轻量,比错误码更结构化,强制调用者处理错误。"
  },
  {
    "instruction": "C++ 中什么是 std::error_code?",
    "input": "",
    "output": "C++11 轻量级错误码,含 int 值和 error_category 引用。可与 std::error_condition 比较跨平台错误。系统调用返回错误码时使用。"
  },
  {
    "instruction": "C++ 中什么是 std::terminate?",
    "input": "",
    "output": "未捕获异常、noexcept 函数抛异常、析构函数抛异常等场景调用 terminate。默认调用 abort(),可设置 terminate_handler 自定义行为。"
  },
  {
    "instruction": "C++ 中什么是异常的代价?",
    "input": "",
    "output": "无异常路径零开销原则:try 块无运行时开销。抛异常代价高(栈展开、类型匹配),但正常路径不受影响。禁用异常 -fno-exceptions 可减小二进制但失去标准库异常支持。"
  },
  {
    "instruction": "C++ 中什么是异常中立的代码?",
    "input": "",
    "output": "函数不捕获异常但正确传播,且不泄漏资源。通过 RAII 实现:局部对象析构释放资源,异常自动向上传播。所有函数应至少是异常中立的。"
  },
  {
    "instruction": "C++ 中什么是函数 try 块?",
    "input": "",
    "output": "function-try-block 将整个函数体包裹在 try 中,如 int f() try { ... } catch(...) { ... }。主要用于构造函数捕获基类和成员初始化异常。"
  },
  {
    "instruction": "C++ 中什么是 noexcept 运算符?",
    "input": "",
    "output": "noexcept(expr) 编译期判断表达式是否可能抛异常,返回 bool。如 static_assert(noexcept(std::swap(x,y))) 检查 swap 是否不抛异常。"
  },
  {
    "instruction": "C++ 中什么是 std::current_exception?",
    "input": "",
    "output": "C++11 获取当前异常的智能指针。在 catch 块中调用返回 exception_ptr,可跨线程传递。rethrow_exception(ptr) 重新抛出。"
  },
  {
    "instruction": "C++ 中什么是嵌套异常?",
    "input": "",
    "output": "C++11 std::nested_exception 混入类,std::throw_with_nested 抛出包含当前异常的新异常。dynamic_pointer_cast<nested_exception> 访问内层异常。"
  },
  {
    "instruction": "C++ 中什么是 RAII?",
    "input": "",
    "output": "资源获取即初始化。构造时获取资源,析构时释放资源。利用栈对象生命周期自动管理资源,是 C++ 最核心的编程范式。"
  },
  {
    "instruction": "C++ 中什么是 copy-and-swap?",
    "input": "",
    "output": "先拷贝构造临时对象,再与当前对象 swap,临时对象析构释放旧资源。实现强异常安全的赋值运算符,消除代码重复。"
  },
  {
    "instruction": "C++ 中什么是 Pimpl?",
    "input": "",
    "output": "Pointer to Implementation,将实现细节移到 .cpp 文件中的内部类,头文件只保留指针。减少编译依赖、稳定 ABI、加速编译。"
  },
  {
    "instruction": "C++ 中什么是 CRTP?",
    "input": "",
    "output": "奇异递归模板模式。class Derived : public Base<Derived>。基类通过 static_cast<Derived*>(this) 调用派生类方法,实现静态多态。"
  },
  {
    "instruction": "C++ 中什么是 NVI?",
    "input": "",
    "output": "Non-Virtual Interface。公有非虚函数定义接口和不变式,调用保护虚函数提供定制点。模板方法模式的 C++ 实现。"
  },
  {
    "instruction": "C++ 中什么是 EBCO?",
    "input": "",
    "output": "空基类优化,空类作为基类时占 0 字节。STL 的 allocator 利用 EBO 减少容器大小。"
  },
  {
    "instruction": "C++ 中什么是 Type Erasure?",
    "input": "",
    "output": "类型擦除,隐藏具体类型通过统一接口操作。如 std::function、std::any。运行时多态无需继承层次。"
  },
  {
    "instruction": "C++ 中什么是 SBO?",
    "input": "",
    "output": "小缓冲区优化/小对象优化。在对象内部存储小数据避免堆分配。如 std::string 的 SSO、std::function 的小可调用对象优化。"
  },
  {
    "instruction": "C++ 中什么是 Expression Template?",
    "input": "",
    "output": "表达式模板,延迟求值避免临时对象。如 D = A + B + C 不产生中间矩阵,生成复合表达式模板对象一次遍历计算。"
  },
  {
    "instruction": "C++ 中什么是 Attitude of Tag Dispatch?",
    "input": "",
    "output": "标签分发,用空结构体标签类型在编译期选择不同重载。如 std::advance 根据 iterator_category 标签选择不同实现。"
  },
  {
    "instruction": "C++ 中什么是 Policy-Based Design?",
    "input": "",
    "output": "基于策略的设计,通过模板参数组合行为。如 Loki 库的 SmartPtr< T, OwnershipPolicy, ConversionPolicy >。编译期组装功能。"
  },
  {
    "instruction": "C++ 中什么是 Scope Guard?",
    "input": "",
    "output": "作用域守卫,退出作用域时执行清理操作。通用实现用 lambda 和 RAII。如 auto guard = make_guard([&]{ cleanup(); });"
  },
  {
    "instruction": "C++ 中什么是 Move-Only Type?",
    "input": "",
    "output": "只可移动不可拷贝的类型。如 unique_ptr、thread、fstream。删除拷贝构造/赋值,提供移动构造/赋值。表示独占资源。"
  },
  {
    "instruction": "C++ 中什么是 Value Semantics?",
    "input": "",
    "output": "值语义,对象拥有独立数据,拷贝产生独立副本。C++ 默认值语义,与 Java 的引用语义不同。值语义更安全但可能拷贝开销大。"
  },
  {
    "instruction": "C++ 中什么是 Reference Semantics?",
    "input": "",
    "output": "引用语义,对象共享数据,拷贝共享同一数据。通过指针或引用实现。C++ 默认值语义,但可用 shared_ptr 实现引用语义。"
  },
  {
    "instruction": "C++ 中什么是 Opaque Pointer?",
    "input": "",
    "output": "不透明指针,头文件只声明指针类型,隐藏实现。与 Pimpl 类似但更简单。C API 常用:typedef struct Foo* FooHandle。"
  },
  {
    "instruction": "C++ 中什么是 Factory Method?",
    "input": "",
    "output": "工厂方法,定义创建对象的接口,子类决定创建哪个类。用虚函数或模板实现,将实例化与使用解耦。"
  },
  {
    "instruction": "C++ 中什么是 Abstract Factory?",
    "input": "",
    "output": "抽象工厂,创建一系列相关对象的接口。如 GUIFactory 创建 Button 和 TextBox 的不同风格实现。"
  },
  {
    "instruction": "C++ 中什么是 Adapter Pattern?",
    "input": "",
    "output": "适配器模式,将一个接口转换为另一个接口。如 std::stack 适配 deque,容器迭代器适配器。"
  },
  {
    "instruction": "C++ 中什么是 Command Pattern?",
    "input": "",
    "output": "命令模式,将操作封装为对象。如 std::function 封装可调用对象,支持撤销/重做队列。"
  },
  {
    "instruction": "C++ 中什么是 Currying in C++?",
    "input": "",
    "output": "C++ 不原生支持柯里化,但可通过 lambda 和 std::bind 部分应用参数。如 auto add = [](int a){ return [a](int b){ return a+b; }; };"
  },
  {
    "instruction": "C++ 中什么是 Monadic Style?",
    "input": "",
    "output": "类似 Haskell Monad 的链式操作风格。C++ 中用 optional::and_then、expected::transform 等实现。C++23 增强了 monadic 接口。"
  },
  {
    "instruction": "C++ 中什么是 Zero-overhead Principle?",
    "input": "",
    "output": "零开销原则:不为未使用的功能付出代价。C++ 抽象机制在未使用时无运行时开销。如虚函数只在多态使用时有开销,模板无运行时开销。"
  },
  {
    "instruction": "C++ 中什么是 Rule of Zero/Five/Three?",
    "input": "",
    "output": "零法则:用 RAII 成员让编译器生成默认操作;三法则:管理资源需自定义析构/拷贝构造/拷贝赋值;五法则:加入移动构造/移动赋值。"
  },
  {
    "instruction": "C++ 中什么是 DRY 原则?",
    "input": "",
    "output": "Don't Repeat Yourself,避免代码重复。通过模板、继承、组合、宏等消除重复。C++ 模板是实现 DRY 的强大工具。"
  },
  {
    "instruction": "C++ 中什么是 KISS 原则?",
    "input": "",
    "output": "Keep It Simple, Stupid,保持简单。避免过度设计,优先使用简单直接的方案。模板元编程虽强大但复杂度应适度。"
  },
  {
    "instruction": "C++ 中什么是 YAGNI 原则?",
    "input": "",
    "output": "You Aren't Gonna Need It,不要提前设计不需要的功能。只在真正需要时添加抽象和泛化。"
  },
  {
    "instruction": "C++ 中什么是 SOLID 原则?",
    "input": "",
    "output": "面向对象设计五大原则:单一职责、开闭原则、里氏替换、接口隔离、依赖反转。C++ 中通过虚函数、模板、Pimpl 等实现。"
  },
  {
    "instruction": "C++ 中什么是防御性编程?",
    "input": "",
    "output": "假设外部输入不可靠,添加检查和断言。如参数验证、边界检查、assert、static_assert。平衡安全性和性能。"
  },
  {
    "instruction": "C++ 中什么是契约编程?",
    "input": "",
    "output": "C++26 预期引入契约,如 preconditions、postconditions、invariants。目前用 assert 和自定义检查宏模拟。"
  },
  {
    "instruction": "C++ 中什么是 const 正确性?",
    "input": "",
    "output": "尽可能使用 const:const 变量、const 引用参数、const 成员函数。防止意外修改,提高代码安全性和可读性。"
  },
  {
    "instruction": "C++ 中什么是单一职责原则?",
    "input": "",
    "output": "一个类只有一个变化原因。类职责过多时拆分为多个类。如将序列化逻辑从业务类中分离。"
  },
  {
    "instruction": "C++ 中什么是开闭原则?",
    "input": "",
    "output": "对扩展开放,对修改关闭。通过虚函数、模板、策略模式等添加新功能而不修改已有代码。"
  },
  {
    "instruction": "C++ 中什么是依赖倒置原则?",
    "input": "",
    "output": "高层模块不依赖低层模块,都依赖抽象。通过接口类(纯虚函数)和依赖注入实现。"
  },
  {
    "instruction": "C++ 中什么是里氏替换原则?",
    "input": "",
    "output": "派生类必须能替换基类而不破坏程序。虚函数覆盖应保持基类契约,不加强前置条件,不减弱后置条件。"
  },
  {
    "instruction": "C++ 中什么是接口隔离原则?",
    "input": "",
    "output": "客户端不应依赖不需要的接口。拆分胖接口为多个小接口。C++ 中通过多继承多个接口类实现。"
  },
  {
    "instruction": "C++ 中什么是头文件?",
    "input": "",
    "output": "头文件声明类、函数、模板供其他翻译单元使用。#include 将头文件内容插入源文件。防止重复包含用 #pragma once 或头文件保护。"
  },
  {
    "instruction": "C++ 中什么是翻译单元?",
    "input": "",
    "output": "一个源文件经过预处理后的结果。每个 .cpp 文件是一个翻译单元,独立编译为 .o 文件,最后链接为可执行文件。"
  },
  {
    "instruction": "C++ 中什么是链接?",
    "input": "",
    "output": "将多个目标文件的符号引用和定义关联起来。链接错误:未定义引用(声明了但没定义)、多重定义(违反 ODR)。"
  },
  {
    "instruction": "C++ 中什么是静态链接和动态链接?",
    "input": "",
    "output": "静态链接将库代码嵌入可执行文件,体积大但独立;动态链接运行时加载共享库(.so/.dll),体积小但依赖环境。"
  },
  {
    "instruction": "C++ 中什么是 CMake?",
    "input": "",
    "output": "跨平台构建系统生成器。CMakeLists.txt 描述项目结构,生成 Makefile 或 IDE 项目。C++ 项目最常用的构建工具。"
  },
  {
    "instruction": "C++ 中什么是 Makefile?",
    "input": "",
    "output": "make 的构建脚本,定义目标、依赖和命令。增量编译只重新编译修改过的文件。CMake 可生成 Makefile。"
  },
  {
    "instruction": "C++ 中什么是包管理器?",
    "input": "",
    "output": "C++ 包管理器:vcpkg(微软)、Conan(去中心化)、xmake(国产)。管理第三方库的下载、编译和集成。"
  },
  {
    "instruction": "C++ 中什么是编译优化级别?",
    "input": "",
    "output": "-O0 无优化(调试);-O1 基本优化;-O2 推荐(安全优化);-O3 激进优化(可能增大体积);-Os 优化体积;-Ofast 包含非标准数学优化。"
  },
  {
    "instruction": "C++ 中什么是 AddressSanitizer?",
    "input": "",
    "output": "编译器插桩工具,检测内存错误:越界、use-after-free、双重释放。编译加 -fsanitize=address,运行时开销约 2x。"
  },
  {
    "instruction": "C++ 中什么是 ThreadSanitizer?",
    "input": "",
    "output": "检测数据竞争的编译器工具。编译加 -fsanitize=thread。发现多线程数据竞争和死锁。"
  },
  {
    "instruction": "C++ 中什么是 UndefinedBehaviorSanitizer?",
    "input": "",
    "output": "检测未定义行为的编译器工具。编译加 -fsanitize=undefined。检测整数溢出、空指针解引用、对齐错误等。"
  },
  {
    "instruction": "C++ 中什么是静态分析?",
    "input": "",
    "output": "不执行代码分析潜在缺陷。工具:clang-tidy(代码规范和缺陷)、cppcheck(常见错误)、Clang Static Analyzer。CI 中集成可提前发现问题。"
  },
  {
    "instruction": "C++ 中什么是 clang-tidy?",
    "input": "",
    "output": "基于 Clang 的 C++ 代码检查工具。检查代码规范、现代化建议、性能优化、Bug 检测。可自动修复部分问题。"
  },
  {
    "instruction": "C++ 中什么是格式化工具?",
    "input": "",
    "output": "clang-format 自动格式化代码,支持多种风格(Google、LLVM、Mozilla 等)。.clang-format 配置文件统一团队风格。"
  },
  {
    "instruction": "C++ 中什么是 include-what-you-use?",
    "input": "",
    "output": "检测头文件包含的工具,报告多余的 #include 和缺失的 #include。减少编译依赖,加速编译。"
  },
  {
    "instruction": "C++ 中什么是预编译头文件?",
    "input": "",
    "output": "将不常变化的头文件预编译为二进制,加速后续编译。如 stdafx.h / pch.h。CMake 的 target_precompile_headers 支持。"
  },
  {
    "instruction": "C++ 中什么是模块?",
    "input": "",
    "output": "C++20 引入,替代头文件。module 声明模块,export 导出声明,import 导入。消除重复编译、宏污染和包含顺序依赖。"
  },
  {
    "instruction": "C++ 中什么是 Unity Build?",
    "input": "",
    "output": "将多个 .cpp 文件 #include 到一个文件中编译,减少重复解析头文件开销。加速编译但可能隐藏符号冲突。"
  },
  {
    "instruction": "C++ 中什么是分布式编译?",
    "input": "",
    "output": "distcc/ccache 等工具加速编译。distcc 将编译任务分发到多台机器;ccache 缓存编译结果避免重复编译。"
  },
  {
    "instruction": "C++ 中什么是 ABI?",
    "input": "",
    "output": "应用二进制接口,定义编译后的接口规范:名称修饰、调用约定、布局、异常处理。不同编译器或版本 ABI 可能不兼容。"
  },
  {
    "instruction": "C++ 中 cin 和 cout 的工作原理是什么?",
    "input": "",
    "output": "cin 是 istream 对象,cout 是 ostream 对象,通过重载 >> 和 << 运算符实现类型安全的输入输出。与 printf/scanf 不同,编译器自动推导类型。"
  },
  {
    "instruction": "C++ 中什么是流操纵器?",
    "input": "",
    "output": "修改流状态的函数或对象。如 setw(n) 设置宽度、setprecision(n) 设置精度、hex 切换十六进制、boolalpha 输出 true/false。"
  },
  {
    "instruction": "C++ 中什么是文件 I/O?",
    "input": "",
    "output": "ifstream 读文件,ofstream 写文件,fstream 读写。构造时打开文件,析构时自动关闭(RAII)。支持文本和二进制模式。"
  },
  {
    "instruction": "C++ 中什么是二进制文件读写?",
    "input": "",
    "output": "用 ios::binary 模式打开文件,read()/write() 操作原始字节。如 out.write(reinterpret_cast<char*>(&data), sizeof(data))。避免文本模式的换行转换。"
  },
  {
    "instruction": "C++ 中什么是流状态?",
    "input": "",
    "output": "流对象维护状态标志:goodbit(正常)、eofbit(到达末尾)、failbit(操作失败)、badbit(严重错误)。用 good()/fail()/eof()/bad() 检查。"
  },
  {
    "instruction": "C++ 中什么是流缓冲区?",
    "input": "",
    "output": "streambuf 是流的底层缓冲区管理类。流通过缓冲区与实际 I/O 设备交互。可自定义 streambuf 实现特殊 I/O 如内存流、网络流。"
  },
  {
    "instruction": "C++ 中 std::stringstream 有什么用?",
    "input": "",
    "output": "字符串流,将字符串作为 I/O 流操作。如 stringstream ss; ss << 42; string s = ss.str(); 实现类型与字符串的相互转换。"
  },
  {
    "instruction": "C++ 中如何格式化输出?",
    "input": "",
    "output": "C++20 std::format 类型安全格式化:format(\"{} + {} = {}\", a, b, a+b)。C++23 std::print 直接输出。替代 printf 和 iostream 操纵器。"
  },
  {
    "instruction": "C++ 中什么是 std::print?",
    "input": "",
    "output": "C++23 引入,类型安全的格式化输出函数。如 print(\"Hello, {}!\\n\", name)。基于 std::format,类似 Python 的 print。"
  },
  {
    "instruction": "C++ 中什么是宽字符流?",
    "input": "",
    "output": "wcin/wcout/wcerr 处理 wchar_t 字符。用于 Unicode 和宽字符集。C++20 的 char8_t 和 char32_t 提供更精确的 Unicode 支持。"
  },
  {
    "instruction": "C++ 中什么是随机数库?",
    "input": "",
    "output": "C++11 <random> 提供引擎和分布。引擎如 mt19937(梅森旋转),分布如 uniform_int_distribution、normal_distribution。替代 rand()。"
  },
  {
    "instruction": "C++ 中什么是 std::valarray?",
    "input": "",
    "output": "数值数组,支持逐元素数学运算。如 valarray<double> a,b; auto c = a + b * sin(a)。专为数值计算优化,但不如 Eigen 等库通用。"
  },
  {
    "instruction": "C++ 中什么是 std::complex?",
    "input": "",
    "output": "复数类型,如 complex<double> z(1.0, 2.0)。支持算术运算、abs、arg、norm、conj 等复数运算。"
  },
  {
    "instruction": "C++ 中什么是 std::ratio?",
    "input": "",
    "output": "C++11 编译期有理数。如 ratio<1, 1000> 表示毫秒。用于 chrono 的 duration 模板参数,实现编译期单位转换。"
  },
  {
    "instruction": "C++ 中什么是 std::bitset?",
    "input": "",
    "output": "固定大小的位集合。如 bitset<8> b(42)。支持位运算、count() 统计 1 的个数、test() 测试某位、to_string/to_ulong 转换。"
  },
  {
    "instruction": "C++ 中什么是 std::integer_sequence?",
    "input": "",
    "output": "编译期整数序列。如 integer_sequence<int, 0,1,2,3>。make_index_sequence<N> 生成 0..N-1。用于展开 tuple 参数包。"
  },
  {
    "instruction": "C++ 中什么是 std::variant 的 visit?",
    "input": "",
    "output": "std::visit 对 variant 应用访问者。如 visit(overloaded{[](int i){...}, [](string s){...}}, v)。C++17 引入,需配合辅助类。"
  },
  {
    "instruction": "C++ 中什么是 std::optional 的 monadic 操作?",
    "input": "",
    "output": "C++23 引入 optional 的 and_then、transform、or_else。如 opt.and_then(f).transform(g) 链式处理可能为空的值。"
  },
  {
    "instruction": "C++ 中什么是 std::expected 的 monadic 操作?",
    "input": "",
    "output": "C++23 引入 expected 的 and_then、transform、or_else、transform_error。链式处理可能出错的操作,类似 Rust 的 Result。"
  },
  {
    "instruction": "C++ 中什么是 std::generator?",
    "input": "",
    "output": "C++23 协程生成器,用 co_yield 惰性产生值序列。如 generator<int> range(int n) { for(int i=0;i<n;++i) co_yield i; }。"
  },
  {
    "instruction": "C++ 中什么是 std::flat_map?",
    "input": "",
    "output": "C++23 引入,基于排序向量的 map。查找 O(log n) 但缓存友好,插入删除 O(n)。适合小数据集和读多写少场景。"
  },
  {
    "instruction": "C++ 中什么是 std::flat_set?",
    "input": "",
    "output": "C++23 引入,基于排序向量的 set。内存连续,缓存友好。适合小数据集,查找比红黑树快但插入删除慢。"
  },
  {
    "instruction": "C++ 中什么是 std::mdspan?",
    "input": "",
    "output": "C++23 引入,多维数组视图。如 mdspan<int, extents<size_t,3,4>> 查看一维数组为 3x4 矩阵。零开销多维索引。"
  },
  {
    "instruction": "C++ 中什么是 std::stacktrace?",
    "input": "",
    "output": "C++23 引入,获取运行时调用栈。如 auto st = stacktrace::current(); 打印函数调用链。调试和错误报告利器。"
  },
  {
    "instruction": "C++ 中什么是 std::unreachable?",
    "input": "",
    "output": "C++23 引入 [[noreturn]] 函数,标记不可达代码。如 default: std::unreachable()。编译器可优化,未定义行为若执行到。"
  },
  {
    "instruction": "C++ 中什么是 std::is_constant_evaluated?",
    "input": "",
    "output": "C++20 函数,在编译期求值返回 true,运行期返回 false。用于同一函数在编译期和运行期选择不同实现。"
  },
  {
    "instruction": "C++ 中什么是 std::to_array?",
    "input": "",
    "output": "C++20 将 C 数组转为 std::array。如 auto arr = std::to_array({1,2,3})。避免手动写数组大小。"
  },
  {
    "instruction": "C++ 中什么是 std::span 的子范围?",
    "input": "",
    "output": "span::first(n)、span::last(n)、span::subspan(offset, count) 创建子视图。零开销切片操作。"
  },
  {
    "instruction": "C++ 中什么是 std::erase_if?",
    "input": "",
    "output": "C++20 容器特化 erase_if。如 erase_if(v, [](int x){return x < 0;}) 删除所有负数。比 erase-remove 更简洁。"
  },
  {
    "instruction": "C++ 中什么是 std::contains?",
    "input": "",
    "output": "C++23 为 set/map/unordered_* 引入 contains() 方法。如 m.contains(key) 返回 bool,比 find() != end() 更直观。"
  },
  {
    "instruction": "C++ 中什么是 std::string 的改进?",
    "input": "",
    "output": "C++17 ssv(string_view 参数);C++20 starts_with/ends_with;C++23 contains。逐步增强字符串处理能力。"
  },
  {
    "instruction": "C++ 中什么是 std::format_to?",
    "input": "",
    "output": "C++20 将格式化结果写入输出迭代器。如 format_to(back_inserter(vec), \"{}\", value)。避免中间字符串分配。"
  },
  {
    "instruction": "C++ 中什么是 std::type_identity?",
    "input": "",
    "output": "C++20 引入,type_identity_t<T> 就是 T 本身。用于阻止模板参数推导:void f(type_identity_t<T> arg) 使调用者必须显式指定 T。"
  },
  {
    "instruction": "C++ 中什么是 std::remove_cvref?",
    "input": "",
    "output": "C++20 引入,移除 const、volatile 和引用修饰。如 remove_cvref_t<const int&> 为 int。比 remove_cv<remove_reference_t<T>> 更简洁。"
  },
  {
    "instruction": "C++ 中什么是 std::common_type?",
    "input": "",
    "output": "计算多个类型的公共类型。如 common_type_t<int, double> 为 double。用于算术运算的返回类型推导。"
  },
  {
    "instruction": "C++ 中什么是 std::invoke?",
    "input": "",
    "output": "C++17 统一调用接口。invoke(f, args...) 可调用函数指针、成员函数指针、仿函数等。is_invocable 检查可调用性。"
  },
  {
    "instruction": "C++ 中什么是 std::not_fn?",
    "input": "",
    "output": "C++17 返回谓词的逻辑非。如 auto not_empty = not_fn(&string::empty)。比手写 lambda 更简洁。"
  },
  {
    "instruction": "C++ 中什么是 std::sample?",
    "input": "",
    "output": "C++17 从范围中随机采样 n 个元素到输出迭代器。如 sample(v.begin(), v.end(), back_inserter(result), n, rng)。"
  },
  {
    "instruction": "C++ 中什么是 std::clamp?",
    "input": "",
    "output": "C++17 将值限制在范围内。如 clamp(x, lo, hi) 返回 max(lo, min(hi, x))。防止值越界。"
  },
  {
    "instruction": "C++ 中什么是 std::gcd 和 std::lcm?",
    "input": "",
    "output": "C++17 数学函数。gcd(a,b) 最大公约数,lcm(a,b) 最小公倍数。编译期可用 constexpr。"
  },
  {
    "instruction": "C++ 中什么是 std::midpoint?",
    "input": "",
    "output": "C++20 安全计算中点。midpoint(a, b) 避免溢出,如 midpoint(INT_MAX, INT_MAX) 不会溢出。比 (a+b)/2 更安全。"
  },
  {
    "instruction": "C++ 中什么是 std::lerp?",
    "input": "",
    "output": "C++20 线性插值。lerp(a, b, t) = a + t*(b-a)。t=0 返回 a,t=1 返回 b。用于动画和数值计算。"
  },
  {
    "instruction": "C++ 中什么是 std::is_sorted?",
    "input": "",
    "output": "检查范围是否已排序。如 is_sorted(v.begin(), v.end()) 返回 bool。is_sorted_until 返回第一个未排序位置。"
  },
  {
    "instruction": "C++ 中什么是 std::shift_left 和 shift_right?",
    "input": "",
    "output": "C++20 范围移位。shift_left(first, last, n) 将元素左移 n 位,末尾留空。比 copy + rotate 更高效。"
  },
  {
    "instruction": "C++ 中什么是 std::ssize?",
    "input": "",
    "output": "C++20 返回有符号的大小。如 for(int i=0; i<ssize(v); ++i) 避免 i < (int)v.size() 的转换。"
  },
  {
    "instruction": "C++ 中什么是 std::empty?",
    "input": "",
    "output": "C++17 统一的空检查。empty(c) 对容器、数组、string 都可用。泛型编程中替代 c.empty()。"
  },
  {
    "instruction": "C++ 中什么是 std::data?",
    "input": "",
    "output": "C++17 获取容器的底层数组指针。data(c) 对 vector、array、string 都可用。泛型编程中替代 c.data()。"
  },
  {
    "instruction": "C++ 中什么是 std::size?",
    "input": "",
    "output": "C++17 统一的大小获取。size(c) 对容器、数组都可用。泛型编程中替代 c.size() 和 sizeof(a)/sizeof(a[0])。"
  },
  {
    "instruction": "C++ 中什么是 std::swap 的 ADL 查找?",
    "input": "",
    "output": "using std::swap; swap(a, b) 先通过 ADL 查找类型特定的 swap,找不到再用 std::swap。自定义类型应提供 swap 在同命名空间。"
  },
  {
    "instruction": "C++ 中什么是 std::hash?",
    "input": "",
    "output": "标准哈希函数对象。可特化 hash<MyType> 支持自定义类型作为 unordered_map 键。默认支持基本类型和 string。"
  },
  {
    "instruction": "C++ 中什么是 std::allocator_traits?",
    "input": "",
    "output": "C++11 引入,提供 allocator 的默认实现。自定义 allocator 只需提供 allocate/deallocate,其余由 traits 补充。简化 allocator 编写。"
  },
  {
    "instruction": "C++ 中什么是 std::scoped_allocator?",
    "input": "",
    "output": "C++11 嵌套容器的分配器传播。如 vector<vector<int, Alloc1>, scoped_allocator_adaptor<Alloc1>> 使内层 vector 也使用 Alloc1。"
  },
  {
    "instruction": "C++ 中什么是 std::pmr 内存资源?",
    "input": "",
    "output": "C++17 多态内存资源。synchronized_pool_resource 线程安全池,unsynchronized_pool_resource 非线程安全池,monotonic_buffer_resource 只增不减。"
  },
  {
    "instruction": "C++ 中什么是 std::pmr::vector?",
    "input": "",
    "output": "C++17 pmr 容器,如 pmr::vector<int> 使用多态内存资源。构造时传入内存资源指针,运行时切换分配策略。"
  },
  {
    "instruction": "C++ 中什么是 std::execution 并行策略?",
    "input": "",
    "output": "C++17 并行 STL 算法。execution::seq 顺序执行,par 并行执行,par_unseq 并行向量化。如 sort(par, v.begin(), v.end())。"
  },
  {
    "instruction": "C++ 中什么是 std::reduce?",
    "input": "",
    "output": "C++17 并行版 accumulate。reduce(par, v.begin(), v.end(), 0) 可并行计算。不保证顺序,操作须满足交换律和结合律。"
  },
  {
    "instruction": "C++ 中什么是 std::transform_reduce?",
    "input": "",
    "output": "C++17 并行版 transform + accumulate。如 transform_reduce(par, v1.begin(), v1.end(), v2.begin(), 0) 计算内积。"
  },
  {
    "instruction": "C++ 中什么是 std::inclusive_scan?",
    "input": "",
    "output": "C++17 前缀和。inclusive_scan(v.begin(), v.end(), out.begin()) 计算包含当前元素的前缀和。exclusive_scan 不包含当前元素。"
  },
  {
    "instruction": "C++ 中什么是 std::adjacent_difference?",
    "input": "",
    "output": "计算相邻元素差值。如 adjacent_difference(v.begin(), v.end(), out.begin()) 输出每个元素与前一个的差。"
  },
  {
    "instruction": "C++ 中什么是 std::partial_sum?",
    "input": "",
    "output": "计算前缀和。partial_sum(v.begin(), v.end(), out.begin()) 输出累计和。可自定义操作。"
  },
  {
    "instruction": "C++ 中什么是 std::inner_product?",
    "input": "",
    "output": "计算内积。inner_product(a.begin(), a.end(), b.begin(), 0) 计算点积。可自定义乘法和加法操作。"
  },
  {
    "instruction": "C++ 中什么是 std::minmax?",
    "input": "",
    "output": "C++11 同时返回最小和最大值。auto [mn, mx] = minmax(a, b)。minmax_element 返回范围的最小最大迭代器。"
  },
  {
    "instruction": "C++ 中什么是 std::min_element 和 max_element?",
    "input": "",
    "output": "返回范围中最小/最大元素的迭代器。如 auto it = max_element(v.begin(), v.end())。可传自定义比较器。"
  },
  {
    "instruction": "C++ 中什么是 std::lexicographical_compare?",
    "input": "",
    "output": "字典序比较两个范围。如 lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()) 判断 a 是否字典序小于 b。"
  },
  {
    "instruction": "C++ 中什么是 std::next_permutation?",
    "input": "",
    "output": "生成下一个排列。循环调用 next_permutation(v.begin(), v.end()) 遍历所有排列。从排序后的范围开始。"
  },
  {
    "instruction": "C++ 中什么是 std::random_shuffle 和 std::shuffle?",
    "input": "",
    "output": "random_shuffle 已废弃(依赖 rand());shuffle 使用随机数引擎,C++11 引入。如 shuffle(v.begin(), v.end(), mt19937{})。"
  },
  {
    "instruction": "C++ 中什么是 std::is_permutation?",
    "input": "",
    "output": "C++11 判断一个范围是否是另一个的排列。如 is_permutation(a.begin(), a.end(), b.begin())。C++14 起接受两个完整范围。"
  }
]

5. 微调

5.1 虚拟环境

bash 复制代码
# 创建虚拟环境
conda create -n lora_peft python=3.10
conda activate lora_peft

# 安装PyTorch
pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 \
--index-url https://mirrors.aliyun.com/pytorch-wheels/cu121 \
--extra-index-url https://download.pytorch.org/whl/cu121 \
--extra-index-url https://mirrors.aliyun.com/pypi/simple/ \
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple/

# 安装依赖包
pip install transformers==4.51.3 accelerate==1.7.0 peft==0.15.2 datasets==3.6.0
pip install tqdm

pip install bitsandbytes==0.43.2  # QLoRA 4-bit

5.3 train_lora.py

python 复制代码
"""LoRA / QLoRA 微调脚本 --- 基于 Qwen3-0.6B 的 C++ 代码生成任务。

支持两种训练模式:
  - LoRA:  全精度加载基座模型,适合显存充裕的场景
  - QLoRA: 4-bit 量化加载基座模型 (NF4 + 双重量化),显存降低约 4 倍

使用示例:

  # 普通 LoRA 训练 (GPU, fp16)
  python train_lora.py --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-lora-cpp

  # 普通 LoRA 训练 (CPU)
  python train_lora.py --device cpu --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-lora-cpp

  # LoRA + bf16 (需要 Ampere+ GPU, 如 RTX 3090/A100)
  python train_lora.py --bf16 --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-lora-cpp

  # LoRA + 梯度检查点 (以计算换显存)
  python train_lora.py --gradient-checkpointing --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-lora-cpp

  # QLoRA 训练 (4-bit 量化, 显存友好)
  python train_lora.py --qlora --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-qlora-cpp

  # QLoRA + 梯度检查点 (最低显存方案, 2080Ti 11GB 可用)
  python train_lora.py --qlora --gradient-checkpointing --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-qlora-cpp

  # QLoRA + bf16 计算 (需要 Ampere+ GPU)
  python train_lora.py --qlora --bf16 --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-qlora-cpp

  # 自定义参数
  python train_lora.py --qlora --lora-r 16 --learning-rate 1e-4 --epochs 5 --batch-size 2 \\
      --data-path data.json --model-path ./Qwen3-0.6B --output-dir ./Qwen3-0.6B-qlora-cpp

  # 从检查点恢复训练
  python train_lora.py --qlora --data-path data.json --model-path ./Qwen3-0.6B \\
      --output-dir ./Qwen3-0.6B-qlora-cpp --resume-from-checkpoint ./Qwen3-0.6B-qlora-cpp/checkpoint-100
"""

import argparse
import os
from pathlib import Path

import torch
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer,
    DataCollatorForSeq2Seq,
    BitsAndBytesConfig,
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from datasets import load_dataset

def parse_args():
    """解析命令行参数,返回包含所有训练配置的 Namespace 对象。"""
    parser = argparse.ArgumentParser(description="LoRA Fine-tuning for Qwen3-0.6B")
    parser.add_argument("--device", choices=["auto", "cpu", "gpu"], default="auto", help="训练设备: auto, cpu, gpu")
    parser.add_argument("--data-path", type=str, required=True, help="训练数据路径 (必填)")
    parser.add_argument("--model-path", type=str, required=True, help="基座模型路径 (必填)")
    parser.add_argument("--output-dir", type=str, required=True, help="LoRA 权重输出目录 (必填)")
    parser.add_argument("--lora-r", type=int, default=8, help="LoRA 秩 (default: 8)")
    parser.add_argument("--lora-alpha", type=int, default=16, help="LoRA alpha (default: 16)")
    parser.add_argument("--lora-dropout", type=float, default=0.05, help="LoRA dropout (default: 0.05)")
    parser.add_argument("--learning-rate", type=float, default=5e-4, help="学习率 (default: 5e-4)")
    parser.add_argument("--epochs", type=int, default=3, help="训练轮数 (default: 3)")
    parser.add_argument("--batch-size", type=int, default=1, help="每设备批大小 (default: 1)")
    parser.add_argument("--grad-acc-steps", type=int, default=4, help="梯度累积步数 (default: 4)")
    parser.add_argument("--max-length", type=int, default=1024, help="最大序列长度 (default: 1024)")
    parser.add_argument("--seed", type=int, default=42, help="随机种子 (default: 42)")
    parser.add_argument(
        "--lr-scheduler",
        type=str,
        default="cosine",
        choices=["linear", "cosine", "constant", "constant_with_warmup"],
        help="学习率调度器",
    )
    parser.add_argument("--warmup-ratio", type=float, default=0.1, help="预热步数占总步数比例 (default: 0.1)")
    parser.add_argument("--weight-decay", type=float, default=0.01, help="权重衰减 (default: 0.01)")
    parser.add_argument("--gradient-checkpointing", action="store_true", help="启用梯度检查点,以计算换显存")
    parser.add_argument("--save-total-limit", type=int, default=1, help="最多保存的检查点数量 (default: 1)")
    parser.add_argument("--num-proc", type=int, default=None, help="数据预处理进程数,默认自动检测 CPU 核数")
    parser.add_argument("--bf16", action="store_true", help="启用 bf16 混合精度训练 (需要 Ampere+ GPU)")
    parser.add_argument("--qlora", action="store_true", help="启用 QLoRA (4-bit 量化加载基座模型,大幅降低显存)")
    parser.add_argument("--eval-ratio", type=float, default=0.2, help="验证集比例(0 表示不划分验证集) (default: 0.2)")
    parser.add_argument("--resume-from-checkpoint", type=str, default=None, help="从检查点恢复训练的路径")
    return parser.parse_args()

def resolve_device(device_choice):
    """根据用户选择解析训练设备。

    Args:
        device_choice: 设备选择,可选 "auto"(自动检测)、"cpu"、"gpu"。

    Returns:
        tuple: (use_gpu: bool, device: str)

    Raises:
        RuntimeError: 选择 gpu 但未检测到 CUDA 设备时抛出。
    """
    use_gpu = False
    if device_choice == "auto":
        use_gpu = torch.cuda.is_available()
    elif device_choice == "gpu":
        if not torch.cuda.is_available():
            raise RuntimeError("指定了 GPU 训练,但未检测到 CUDA 设备")
        use_gpu = True
    device = "cuda" if use_gpu else "cpu"
    return use_gpu, device

def validate_paths(data_path, model_path):
    """校验训练数据和基座模型路径是否存在。

    Args:
        data_path: 训练数据文件路径。
        model_path: 基座模型目录路径。

    Raises:
        FileNotFoundError: 路径不存在时抛出。
    """
    if not Path(data_path).exists():
        raise FileNotFoundError(f"训练数据不存在: {data_path}")
    if not Path(model_path).exists():
        raise FileNotFoundError(f"基座模型路径不存在: {model_path}")

def format_prompt_batch(samples, tokenizer, max_length):
    """批量将原始样本格式化为 ChatML 格式并构建训练标签。

    Prompt 部分的 label 设为 -100(不计入 loss),仅对 assistant 回复部分计算损失。

    Args:
        samples: 数据集批次,包含 "instruction" 和 "output" 字段。
        tokenizer: 分词器实例。
        max_length: 最大序列长度,超出部分将被截断。

    Returns:
        dict: 包含 "input_ids"、"attention_mask"、"labels" 的字典。
    """
    prompts = [f"<|im_start|>user\n{inst}<|im_end|>\n<|im_start|>assistant\n" for inst in samples["instruction"]]
    responses = [f"{out}<|im_end|>" for out in samples["output"]]
    full_texts = [p + r for p, r in zip(prompts, responses)]

    prompt_enc = tokenizer(prompts, add_special_tokens=False)
    full_enc = tokenizer(
        full_texts,
        truncation=True,
        max_length=max_length,
        add_special_tokens=False,
    )

    all_labels = []
    for i in range(len(prompts)):
        prompt_len = len(prompt_enc["input_ids"][i])
        full_len = len(full_enc["input_ids"][i])
        effective_prompt_len = min(prompt_len, full_len)
        labels = [-100] * effective_prompt_len + full_enc["input_ids"][i][effective_prompt_len:]
        labels = labels[:full_len]
        all_labels.append(labels)

    return {
        "input_ids": full_enc["input_ids"],
        "attention_mask": full_enc["attention_mask"],
        "labels": all_labels,
    }

def main():
    """主训练流程:解析参数 -> 加载模型和数据 -> 配置 LoRA -> 执行训练 -> 保存权重。"""
    args = parse_args()
    use_gpu, device = resolve_device(args.device)
    print(f"使用设备: {device}")

    data_path = args.data_path
    model_path = args.model_path

    validate_paths(data_path, model_path)

    tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=True)
    tokenizer.pad_token = tokenizer.eos_token

    use_qlora = args.qlora and use_gpu
    if use_qlora:
        if not use_gpu:
            raise RuntimeError("QLoRA 需要 GPU 支持,当前未检测到 CUDA 设备")
        if args.bf16:
            compute_dtype = torch.bfloat16
        else:
            compute_dtype = torch.float16

    output_dir = args.output_dir

    use_bf16 = args.bf16 and use_gpu
    if use_bf16:
        dtype = torch.bfloat16
    elif use_gpu:
        dtype = torch.float16
    else:
        dtype = torch.float32

    model_kwargs = {"use_cache": False}
    if use_qlora:
        bnb_config = BitsAndBytesConfig(
            load_in_4bit=True,
            bnb_4bit_quant_type="nf4",
            bnb_4bit_compute_dtype=compute_dtype,
            bnb_4bit_use_double_quant=True,
        )
        model_kwargs["quantization_config"] = bnb_config
        model_kwargs["device_map"] = "auto"
        model_kwargs["attn_implementation"] = "sdpa"
    else:
        model_kwargs["torch_dtype"] = dtype
        if use_gpu:
            model_kwargs["device_map"] = "auto"
            model_kwargs["attn_implementation"] = "sdpa"

    model = AutoModelForCausalLM.from_pretrained(model_path, **model_kwargs)

    if use_qlora:
        model = prepare_model_for_kbit_training(model)
    if args.gradient_checkpointing:
        model.gradient_checkpointing_enable()
        model.enable_input_require_grads()

    lora_config = LoraConfig(
        r=args.lora_r,
        lora_alpha=args.lora_alpha,
        target_modules="all-linear",
        lora_dropout=args.lora_dropout,
        bias="none",
        task_type="CAUSAL_LM",
    )
    model = get_peft_model(model, lora_config)
    model.enable_input_require_grads()
    model.config.use_cache = False
    model.print_trainable_parameters()

    dataset = load_dataset("json", data_files=data_path, split="train")

    if not (0.0 <= args.eval_ratio < 1.0):
        raise ValueError(f"eval_ratio 必须在 [0, 1) 范围内,当前值: {args.eval_ratio}")
    if args.eval_ratio > 0.0:
        split = dataset.train_test_split(test_size=args.eval_ratio, seed=args.seed)
        train_ds = split["train"]
        eval_ds = split["test"]
        print(f"训练集: {len(train_ds)} 条, 验证集: {len(eval_ds)} 条")
    else:
        train_ds = dataset
        eval_ds = None
        print(f"训练集: {len(train_ds)} 条, 无验证集")

    num_proc = args.num_proc or min(os.cpu_count() or 1, 8)

    train_ds = train_ds.map(
        format_prompt_batch,
        fn_kwargs={"tokenizer": tokenizer, "max_length": args.max_length},
        batched=True,
        remove_columns=train_ds.column_names,
        num_proc=num_proc,
        desc="Tokenizing train",
    )

    if eval_ds is not None:
        eval_ds = eval_ds.map(
            format_prompt_batch,
            fn_kwargs={"tokenizer": tokenizer, "max_length": args.max_length},
            batched=True,
            remove_columns=eval_ds.column_names,
            num_proc=num_proc,
            desc="Tokenizing eval",
        )

    data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True)

    optim = "adamw_torch_fused" if use_gpu else "adamw_torch"

    save_limit = args.save_total_limit if eval_ds is None else max(args.save_total_limit, args.epochs)

    training_args = TrainingArguments(  # pylint: disable=unexpected-keyword-arg
        output_dir=output_dir,
        per_device_train_batch_size=args.batch_size,
        gradient_accumulation_steps=args.grad_acc_steps,
        learning_rate=args.learning_rate,
        num_train_epochs=args.epochs,
        lr_scheduler_type=args.lr_scheduler,
        warmup_ratio=args.warmup_ratio,
        weight_decay=args.weight_decay,
        logging_steps=1,
        save_strategy="epoch",
        save_total_limit=save_limit,
        fp16=use_gpu and not use_bf16,
        bf16=use_bf16,
        use_cpu=not use_gpu,
        optim=optim,
        gradient_checkpointing=args.gradient_checkpointing,
        seed=args.seed,
        report_to="none",
        eval_strategy="epoch" if eval_ds is not None else "no",
        load_best_model_at_end=eval_ds is not None,
        metric_for_best_model="loss" if eval_ds is not None else None,
    )

    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=train_ds,
        eval_dataset=eval_ds,
        data_collator=data_collator,
    )

    trainer.train(resume_from_checkpoint=args.resume_from_checkpoint)
    model.save_pretrained(output_dir)
    print(f"训练完成({device}), LoRA权重已保存至 {output_dir}")

if __name__ == "__main__":
    main()

5.3 merge_lora.py

python 复制代码
"""LoRA / QLoRA 权重合并脚本 --- 将训练好的 LoRA 适配器合并回基座模型。

功能:
  - 加载基座模型和 LoRA 权重,执行 merge_and_unload 合并
  - 支持指定输出精度 (fp16 / bf16 / fp32 / auto)
  - 合并前估算模型大小并检查磁盘空间
  - 可选: 合并后生成验证、清理 LoRA 权重目录、保存合并元数据

使用示例:

  # 基本合并 (自动检测精度)
  python merge_lora.py --model-path ./Qwen3-0.6B --lora-path ./Qwen3-0.6B-lora-cpp --output-path ./Qwen3-0.6B-merged-cpp

  # 指定输出精度为 fp16
  python merge_lora.py --dtype fp16 --model-path ./Qwen3-0.6B --lora-path ./Qwen3-0.6B-lora-cpp --output-path ./Qwen3-0.6B-merged-cpp

  # 合并并验证生成效果
  python merge_lora.py --verify --model-path ./Qwen3-0.6B --lora-path ./Qwen3-0.6B-lora-cpp --output-path ./Qwen3-0.6B-merged-cpp

  # 合并后删除 LoRA 权重目录释放空间
  python merge_lora.py --cleanup-lora --model-path ./Qwen3-0.6B --lora-path ./Qwen3-0.6B-lora-cpp --output-path ./Qwen3-0.6B-merged-cpp
"""

import argparse
import json
import shutil
import time
from datetime import datetime, timezone
from pathlib import Path

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

DTYPE_MAP = {
    "fp16": torch.float16,
    "bf16": torch.bfloat16,
    "fp32": torch.float32,
    "auto": None,
}

DTYPE_BYTES = {
    torch.float16: 2,
    torch.bfloat16: 2,
    torch.float32: 4,
}

def parse_args():
    """解析命令行参数,返回包含所有合并配置的 Namespace 对象。"""
    parser = argparse.ArgumentParser(description="合并 LoRA 权重与基座模型")
    parser.add_argument("--device", choices=["auto", "cpu", "gpu"], default="auto", help="合并设备: auto, cpu, gpu")
    parser.add_argument(
        "--dtype", choices=["auto", "fp16", "bf16", "fp32"], default="auto", help="合并模型精度: auto, fp16, bf16, fp32"
    )
    parser.add_argument("--model-path", type=str, required=True, help="基座模型路径")
    parser.add_argument("--lora-path", type=str, required=True, help="LoRA 权重路径")
    parser.add_argument("--output-path", type=str, required=True, help="合并后模型保存路径")
    parser.add_argument("--verify", action="store_true", help="合并后进行简单生成验证")
    parser.add_argument("--cleanup-lora", action="store_true", help="合并成功后删除 LoRA 权重目录,释放磁盘空间")
    parser.add_argument("--max-shard-size", type=str, default="5GB", help="模型分片最大大小 (default: 5GB)")
    return parser.parse_args()

def resolve_device(device_choice):
    """根据用户选择解析运行设备。

    Args:
        device_choice: 设备选择,可选 "auto"(自动检测)、"cpu"、"gpu"。

    Returns:
        tuple: (use_gpu: bool, device: str)

    Raises:
        RuntimeError: 选择 gpu 但未检测到 CUDA 设备时抛出。
    """
    use_gpu = False
    if device_choice == "auto":
        use_gpu = torch.cuda.is_available()
    elif device_choice == "gpu":
        if not torch.cuda.is_available():
            raise RuntimeError("指定了 GPU,但未检测到 CUDA 设备")
        use_gpu = True
    device = "cuda" if use_gpu else "cpu"
    return use_gpu, device

def validate_paths(model_path, lora_path):
    """校验基座模型和 LoRA 权重路径是否存在。

    Args:
        model_path: 基座模型目录路径。
        lora_path: LoRA 权重目录路径。

    Raises:
        FileNotFoundError: 路径不存在时抛出。
    """
    if not Path(model_path).exists():
        raise FileNotFoundError(f"基座模型路径不存在: {model_path}")
    if not Path(lora_path).exists():
        raise FileNotFoundError(f"LoRA 权重路径不存在: {lora_path}")

def estimate_model_size(model, dtype):
    """估算模型在指定精度下的参数量和磁盘占用。

    Args:
        model: PyTorch 模型实例。
        dtype: 目标精度类型 (torch.float16 / torch.bfloat16 / torch.float32)。

    Returns:
        tuple: (total_params: int, estimated_bytes: int)

    Raises:
        ValueError: dtype 不在 DTYPE_BYTES 中时抛出。
    """
    total_params = sum(p.numel() for p in model.parameters())
    if dtype not in DTYPE_BYTES:
        raise ValueError(f"不支持的精度类型: {dtype},可选: {list(DTYPE_BYTES.keys())}")
    bytes_per_param = DTYPE_BYTES[dtype]
    estimated_bytes = total_params * bytes_per_param
    return total_params, estimated_bytes

def check_disk_space(output_path, required_bytes):
    """检查输出路径所在磁盘是否有足够空间保存模型(含 20% 安全余量)。

    当输出路径不存在时,递归向上查找已存在的祖先路径进行查询。

    Args:
        output_path: 模型输出目录路径。
        required_bytes: 估算的模型磁盘占用字节数。

    Raises:
        RuntimeError: 磁盘空间不足时抛出。
    """
    output_dir = Path(output_path).resolve()
    # 递归向上查找存在的祖先路径用于磁盘空间查询
    check_path = output_dir
    while not check_path.exists():
        check_path = check_path.parent
    stat = shutil.disk_usage(check_path)
    available_gb = stat.free / (1024**3)
    required_gb = required_bytes / (1024**3) * 1.2
    if stat.free < required_bytes * 1.2:
        raise RuntimeError(f"磁盘空间不足: 需要 ~{required_gb:.1f}GB, 可用 {available_gb:.1f}GB")
    print(f"磁盘空间检查通过: 需要 ~{required_gb:.1f}GB, 可用 {available_gb:.1f}GB")

def verify_model(model, tokenizer, device):
    """对合并后的模型进行简单生成验证,确认模型可正常推理。

    Args:
        model: 合并后的模型实例。
        tokenizer: 对应的分词器实例。
        device: 运行设备 ("cuda" 或 "cpu")。
    """
    prompt = "<|im_start|>user\n你好<|im_end|>\n<|im_start|>assistant\n"
    inputs = tokenizer(prompt, return_tensors="pt").to(device)
    model.config.use_cache = True
    with torch.no_grad():
        outputs = model.generate(
            **inputs,
            max_new_tokens=32,
            do_sample=False,
            pad_token_id=tokenizer.eos_token_id,
        )
    model.config.use_cache = False
    response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1] :], skip_special_tokens=True)
    print(f"验证生成结果: {response.strip()}")

def save_merge_info(output_path, model_path, lora_path, dtype_name, total_params):
    """保存合并元数据到 merge_info.json,记录基座模型、LoRA 路径、精度等信息。

    Args:
        output_path: 合并输出目录路径。
        model_path: 基座模型路径。
        lora_path: LoRA 权重路径。
        dtype_name: 精度名称 (如 "fp16"、"bf16"、"fp32")。
        total_params: 模型总参数量。
    """
    info = {
        "base_model": str(model_path),
        "lora_path": str(lora_path),
        "dtype": dtype_name,
        "total_parameters": total_params,
        "merged_at": datetime.now(timezone.utc).isoformat(),
    }
    info_path = Path(output_path) / "merge_info.json"
    with open(info_path, "w", encoding="utf-8") as f:
        json.dump(info, f, indent=2, ensure_ascii=False)
    print(f"合并元数据已保存至 {info_path}")

def main():
    """主合并流程:解析参数 -> 加载基座模型和 LoRA -> 合并权重 -> 保存模型。"""
    start_time = time.time()
    args = parse_args()
    use_gpu, device = resolve_device(args.device)
    print(f"使用设备: {device}")

    model_path = args.model_path
    lora_path = args.lora_path
    output_path = args.output_path

    validate_paths(model_path, lora_path)

    print(f"基座模型路径: {model_path}")
    print(f"LoRA 权重路径: {lora_path}")
    print(f"合并输出路径: {output_path}")

    dtype = DTYPE_MAP[args.dtype]
    if dtype is None:
        dtype = torch.float16 if use_gpu else torch.float32
    dtype_name = {torch.float16: "fp16", torch.bfloat16: "bf16", torch.float32: "fp32"}[dtype]
    print(f"输出精度: {args.dtype} -> {dtype_name}")

    tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=True)

    model_kwargs = {
        "torch_dtype": dtype,
        "low_cpu_mem_usage": True,
    }
    if use_gpu:
        model_kwargs["device_map"] = "auto"
        model_kwargs["attn_implementation"] = "sdpa"

    print("加载基座模型...")
    model = AutoModelForCausalLM.from_pretrained(model_path, **model_kwargs)

    print("加载 LoRA 权重...")
    model = PeftModel.from_pretrained(model, lora_path)

    print("合并 LoRA 权重到基座模型...")
    model = model.merge_and_unload()

    total_params, estimated_bytes = estimate_model_size(model, dtype)
    print(f"模型参数量: {total_params:,} ({total_params / 1e9:.2f}B)")
    print(f"估算磁盘大小: {estimated_bytes / (1024**3):.2f}GB")

    check_disk_space(output_path, estimated_bytes)

    if args.verify:
        print("验证合并结果...")
        verify_model(model, tokenizer, device)

    print(f"保存合并后的模型至 {output_path} ...")
    try:
        model.save_pretrained(
            output_path,
            safe_serialization=True,
            max_shard_size=args.max_shard_size,
        )
        tokenizer.save_pretrained(output_path)
    except Exception as e:
        partial_dir = Path(output_path)
        if partial_dir.exists():
            shutil.rmtree(partial_dir, ignore_errors=True)
        raise RuntimeError(f"保存模型失败,已清理不完整输出: {e}") from e

    save_merge_info(output_path, model_path, lora_path, dtype_name, total_params)

    if args.cleanup_lora:
        print(f"清理 LoRA 权重目录: {lora_path}")
        try:
            shutil.rmtree(lora_path)
            print("LoRA 权重已删除")
        except OSError as e:
            print(f"警告: LoRA 权重删除失败 ({e}),请手动清理: {lora_path}")

    elapsed = time.time() - start_time
    print(f"合并完成!耗时 {elapsed:.1f}s")

if __name__ == "__main__":
    main()

5.4 LoRA

bash 复制代码
# ═════════════════════════════════
# 初始状态
# ll -h ~/ws/models
# total 12K
# drwxrwxr-x  3 u2x u2x 4.0K  6月 13 22:06 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# ═════════════════════════════════

# 切换工作目录与虚拟环境
cd ~/ws
conda activate lora_peft

# ═════════════════════════════════
# 1. LoRA 微调
# 全精度加载基座模型,训练 LoRA 适配器 (fp16 权重)
# 显存需求: ~4GB (0.6B 模型)
#
# ll -h ~/ws/models
# total 16K
# drwxrwxr-x  4 u2x u2x 4.0K  6月 13 22:08 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:10 Qwen3-0.6B-lora-cpp-f16/
# ═════════════════════════════════
python train_lora.py \
  --data-path  ~/ws/datasets/llm-cpp/llm-cpp.json \
  --model-path ~/ws/models/Qwen3-0.6B \
  --output-dir ~/ws/models/Qwen3-0.6B-lora-cpp-f16

# ═════════════════════════════════
# 2. 合并 LoRA 权重到基座模型
# 将 LoRA 适配器融合进基座,生成独立完整模型,LoRA 不再可分离
#
# ll -h ~/ws/models
# total 20K
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:15 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:10 Qwen3-0.6B-lora-cpp-f16/
# drwxrwxr-x  2 u2x u2x 4.0K  6月 13 22:15 Qwen3-0.6B-merge-cpp-f16/
# ═════════════════════════════════
python merge_lora.py \
  --model-path  ~/ws/models/Qwen3-0.6B \
  --lora-path   ~/ws/models/Qwen3-0.6B-lora-cpp-f16 \
  --output-path ~/ws/models/Qwen3-0.6B-merge-cpp-f16

# 切换工作目录与虚拟环境
cd ~/ws/llama.cpp
conda activate llama.cpp

# ═════════════════════════════════
# 3. 合并后模型转 GGUF
# HuggingFace 格式 → GGUF F16 (无损中间格式)
#
# ll -h ~/ws/models
# total 1.2G
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:16 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:10 Qwen3-0.6B-lora-cpp-f16/
# drwxrwxr-x  2 u2x u2x 4.0K  6月 13 22:15 Qwen3-0.6B-merge-cpp-f16/
# -rw-rw-r--  1 u2x u2x 1.2G  6月 13 22:16 Qwen3-0.6B-merge-cpp-f16.gguf
# ═════════════════════════════════
python convert_hf_to_gguf.py ~/ws/models/Qwen3-0.6B-merge-cpp-f16 \
  --outfile ~/ws/models/Qwen3-0.6B-merge-cpp-f16.gguf \
  --outtype f16

# ═════════════════════════════════
# 4. GGUF F16 → Q4_K_M 量化
# F16 (~1.2GB) → Q4_K_M (~400MB),体积减少约 2/3
# Q4_K_M: 4-bit 量化,兼顾精度与速度
#
# ll -h ~/ws/models
# total 1.5G
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:17 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:10 Qwen3-0.6B-lora-cpp-f16/
# drwxrwxr-x  2 u2x u2x 4.0K  6月 13 22:15 Qwen3-0.6B-merge-cpp-f16/
# -rw-rw-r--  1 u2x u2x 1.2G  6月 13 22:16 Qwen3-0.6B-merge-cpp-f16.gguf
# -rw-rw-r--  1 u2x u2x 379M  6月 13 22:17 Qwen3-0.6B-merge-cpp-q4_k_m.gguf
# ═════════════════════════════════
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib
~/ws/llama.cpp/install/cuda/bin/llama-quantize \
  ~/ws/models/Qwen3-0.6B-merge-cpp-f16.gguf \
  ~/ws/models/Qwen3-0.6B-merge-cpp-q4_k_m.gguf \
  Q4_K_M

# ═════════════════════════════════
# 5. llama.cpp 部署
# -m: 量化模型路径    -ngl: GPU 层数(99=全部)
# -c: 上下文长度      -n: 最大生成 token 数
# ═════════════════════════════════
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib
~/ws/llama.cpp/install/cuda/bin/llama-server \
  -m ~/ws/models/Qwen3-0.6B-merge-cpp-q4_k_m.gguf \
  -ngl 99 -c 2048 -n 512 \
  --host 0.0.0.0 --port 8080

# ═════════════════════════════════
# 6. 验证
# OpenAI 兼容 API 测试
# ═════════════════════════════════
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3",
    "messages": [
      {"role": "user", "content": "介绍C++17完美转发"}
    ],
    "temperature": 0.7,
    "max_tokens": 300
  }'

5.5 QLoRA

bash 复制代码
# ═════════════════════════════════
# 初始状态
# ll -h ~/ws/models
# total 12K
# drwxrwxr-x  3 u2x u2x 4.0K  6月 13 22:06 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# ═════════════════════════════════

# 切换工作目录与虚拟环境
cd ~/ws
conda activate lora_peft

# ═════════════════════════════════
# 4-bit NF4 量化加载基座,仅训练 fp16 LoRA 适配器
# 显存需求: ~2GB (0.6B 模型),比普通 LoRA 节省约一半
#
# ll -h ~/ws/models
# total 16K
# drwxrwxr-x  4 u2x u2x 4.0K  6月 13 22:20 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:24 Qwen3-0.6B-qlora-cpp-f16/
# ═════════════════════════════════
python train_lora.py --qlora \
  --data-path  ~/ws/datasets/llm-cpp/llm-cpp.json \
  --model-path ~/ws/models/Qwen3-0.6B \
  --output-dir ~/ws/models/Qwen3-0.6B-qlora-cpp-f16

# 切换工作目录与虚拟环境
cd ~/ws/llama.cpp
conda activate llama.cpp

# ═════════════════════════════════
# 2. 基座模型转 GGUF 并量化
# 基座模型: HuggingFace → GGUF F16 → Q4_K_M
# 注意: 基座用 Q4_K_M 而非 F16,保持与训练时 4-bit 量化级别一致
#       否则 LoRA 适配的"修正量"与基座精度不匹配,效果打折
#
# ll -h ~/ws/models
# total 1.5G
# drwxrwxr-x  4 u2x u2x 4.0K  6月 13 22:25 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# -rw-rw-r--  1 u2x u2x 1.5G  6月 13 22:25 Qwen3-0.6B-f16.gguf
# -rw-rw-r--  1 u2x u2x 462M  6月 13 22:25 Qwen3-0.6B-q4_k_m.gguf
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:24 Qwen3-0.6B-qlora-cpp-f16/
# ═════════════════════════════════
# 2a. 转 F16 中间格式 (无损,~1.2GB)
python convert_hf_to_gguf.py ~/ws/models/Qwen3-0.6B \
  --outfile ~/ws/models/Qwen3-0.6B-f16.gguf \
  --outtype f16

# 2b. F16 → Q4_K_M 量化 (最终基座,~400MB)
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib
~/ws/llama.cpp/build_b9555_cuda/bin/llama-quantize \
  ~/ws/models/Qwen3-0.6B-f16.gguf \
  ~/ws/models/Qwen3-0.6B-q4_k_m.gguf \
  Q4_K_M

# ═════════════════════════════════
# 3. LoRA 适配器转 GGUF
# LoRA 适配器保持 fp16,不量化 (体积仅几MB,量化会损失有效信号)
# --base: 指定本地基座模型路径 (避免被误认为 HF 仓库名)
#
# ll -h ~/ws/models
# total 1.9G
# drwxrwxr-x  4 u2x u2x 4.0K  6月 13 22:26 ./
# drwxrwxr-x 14 u2x u2x 4.0K  6月 13 22:06 ../
# drwxrwxr-x  3 u2x u2x 4.0K  6月  8 22:20 Qwen3-0.6B/
# -rw-rw-r--  1 u2x u2x 1.5G  6月 13 22:25 Qwen3-0.6B-f16.gguf
# -rw-rw-r--  1 u2x u2x 462M  6月 13 22:25 Qwen3-0.6B-q4_k_m.gguf
# drwxrwxr-x  5 u2x u2x 4.0K  6月 13 22:24 Qwen3-0.6B-qlora-cpp-f16/
# -rw-rw-r--  1 u2x u2x 9.7M  6月 13 22:26 Qwen3-0.6B-qlora-cpp-f16.gguf
# ═════════════════════════════════
python convert_lora_to_gguf.py ~/ws/models/Qwen3-0.6B-qlora-cpp-f16 \
  --base ~/ws/models/Qwen3-0.6B \
  --outfile ~/ws/models/Qwen3-0.6B-qlora-cpp-f16.gguf \
  --outtype f16

# ═════════════════════════════════
# 4. 部署
# -m:   量化基座模型 (Q4_K_M)
# --lora: fp16 LoRA 适配器 (运行时叠加,无需合并)
# -ngl: GPU 层数 (99=全部)  -c: 上下文长度  -n: 最大生成 token 数
# 优势: 同一基座可切换不同 LoRA,无需重新部署
# ═════════════════════════════════
export LD_LIBRARY_PATH=~/ws/llama.cpp/install/cuda/lib
~/ws/llama.cpp/build_b9555_cuda/bin/llama-server \
  -m ~/ws/models/Qwen3-0.6B-q4_k_m.gguf \
  --lora ~/ws/models/Qwen3-0.6B-qlora-cpp-f16.gguf \
  -ngl 99 -c 2048 -n 512 \
  --host 0.0.0.0 --port 8080

# ═════════════════════════════════
# 5. 验证
# OpenAI 兼容 API 测试
# ═════════════════════════════════
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3",
    "messages": [
      {"role": "user", "content": "介绍C++17完美转发"}
    ],
    "temperature": 0.7,
    "max_tokens": 300
  }'
相关推荐
Ada's1 小时前
【智能体系统AgentOS】核心22:Evo
人工智能
探物 AI1 小时前
零基础入门3D点云深度学习:从PointNet开始,理解3D数据处理
人工智能·深度学习·3d
段一凡-华北理工大学1 小时前
LangChain框架在高炉炼铁智能化领域的应用~系列文章02:从Prompt开始,让大模型听懂高炉的“黑话“
大数据·人工智能·学习·架构·langchain·prompt·高炉炼铁
硅谷秋水1 小时前
Nautilus:从单一提示词到即插即用机器人学习
人工智能·深度学习·机器学习·机器人
工头阿乐1 小时前
Claude Code 安装手册
人工智能
洛星核1 小时前
Aider 安装、使用方法详细全解
人工智能·github·人机交互·ai编程·agi
cxr8281 小时前
蜂群智能系统中“非必要不添加“原则的有效性再审视:基于分布式决策与通信复杂度的理论推导
人工智能·分布式·智能体
Asize1 小时前
Bun + TypeScript:AI 时代的后端开发入门
人工智能·typescript·bun
Jerryhut1 小时前
opencv对齐算法及其应用
人工智能·opencv·算法