C++项目用CLAUDE.md锁定编码标准与内存管理规范
Claude Code的「项目宪法」Claude Code 是 Anthropic 推出的终端内 AI 编程助手而CLAUDE.md文件就是它的项目级配置入口。你可以把它理解为一份「项目宪法」——所有 Claude Code 在项目内的回答、生成代码、重构建议都会遵循这份文件里的规则。对于 C 项目来说最让开发者头疼的两件事往往是标准版本不统一有人偷偷用了 C20 特性但项目只支持 C17和内存管理风格混乱裸指针和智能指针混用所有权不清。CLAUDE.md恰好能一次性解决这两个问题。1. CLAUDE.md 的基本用法在项目根目录下创建CLAUDE.md文件Claude Code 会在每次启动时自动加载。文件采用 Markdown 格式内容可以是任何你希望 Claude 遵守的规则、风格指南或项目背景信息。# CLAUDE.md 基本结构示例 项目背景 这是一个 C 游戏服务端项目需要处理高并发网络请求。 编码规范 使用 C17 标准 统一使用智能指针管理内存 命名风格遵循 Google C Style Guide文件生效后当你在项目中让 Claude Code 生成代码或重构时它会自动遵循你设定的约束。不需要每次都手动提醒「请用 C17」或「不要用裸指针」。2. 锁定 C 标准版本C 各版本之间的特性差异很大——C14、C17、C20 甚至 C23 都引入了大量新语法和库。如果你的项目 CI 环境只支持 C17但 AI 生成了一段包含std::span或concepts的代码后续排查会非常痛苦。在CLAUDE.md中明确声明标准版本是最直接的解法## C 标准要求 - 本项目严格使用 C17 标准CMake 中已设置 set(CMAKE_CXX_STANDARD 17) - 禁止使用 C20/23 特性包括但不限于 - Conceptsrequires、concept - Rangesstd::ranges - std::span - 协程co_await、co_return - std::format请使用 fmtlib/fmt 库替代 - 三路比较运算符 - 可以使用 C17 特性 - if constexpr - 结构化绑定auto [a, b] ... - std::optional、std::variant、std::string_view - 折叠表达式这种「白名单 黑名单」的方式能让 AI 精确知道你项目的技术边界。如果你还处于从 C14 升级到 C17 的过渡期也可以把规则写得更有针对性## 过渡期标准策略 - 核心模块使用 C17但需要保持对 C14 编译器的兼容性 - 新代码中优先使用 C17 特性但需要提供 C14 的降级路径 - std::optional 和 std::variant 暂时禁止请使用 Boost 对应实现3. 锁定内存管理规范C 内存管理是 Bug 的重灾区。不同团队、不同模块之间的内存管理风格一旦不统一代码审查成本会直线上升。借助CLAUDE.md你可以把团队的内存管理约定固化成 AI 必须遵守的规则。3.1 智能指针优先策略如果你的项目已经完全拥抱现代 C可以这样写## 内存管理规范 - 严格禁止使用裸指针管理资源所有权以下情况除外 - 与 C 接口交互必须封装在 RAII 包装内 - 作为函数参数传递非拥有指针用 T* 表示「可选引用」不转移所有权 - new 和 delete 关键字禁止出现在业务代码中 - 优先使用工厂函数 - std::make_uniqueT(...) 创建独占所有权 - std::make_sharedT(...) 创建共享所有权 - 禁止使用 std::auto_ptrC17 中已被移除3.2 所有权语义明确化内存问题的根源往往不是「用没用智能指针」而是所有权不清晰。可以在CLAUDE.md中直接约定所有权传递规则## 所有权传递规范 - 函数如果接管对象所有权参数使用 std::unique_ptrT 按值传递 - 函数如果只是临时使用对象参数使用 const T 或 T* - 函数如果返回新创建的对象必须返回 std::unique_ptrT - 禁止返回裸指针指向堆上分配的新对象极易导致内存泄漏 - 使用 std::weak_ptr 打破 std::shared_ptr 循环引用3.3 性能敏感场景的例外规则如果你在做游戏引擎、高频交易或嵌入式开发可能需要在某些模块中放宽规则## 内存管理例外 - 渲染管线、网络收发包缓冲区等热路径代码可以使用裸指针和自定义内存池 - 例外模块必须满足以下条件 - 在类注释中明确说明内存管理策略 - 提供 RAII 守卫或作用域级别的自动回收机制 - 通过 AddressSanitizer / Valgrind 验证无泄漏 - Claude Code 在生成例外模块代码时必须同时生成对应的 RAII 包装4. 进阶组合约束与工具链锁定单独的 C 标准和内存规范已经很实用了但CLAUDE.md的强大之处在于你可以把所有约束「组合」起来形成完整的技术栈锁定。4.1 编译器和平台锁定## 编译与平台约束 - 编译器GCC 11 / Clang 14 / MSVC 2022 - 目标平台Linux x86_64Ubuntu 22.04、Windows 10 - CMake 最低版本3.20 - 开启编译选项-Wall -Wextra -Wpedantic -Werror - 使用 AddressSanitizer-fsanitizeaddress进行开发环境测试4.2 第三方库白名单## 依赖库规范 - 允许使用的第三方库 - Boost仅限 asio、beast、json 模块 - fmtlib/fmt 10.x - Google Test 1.14 - spdlog 1.12 - 禁止引入新的第三方库除非经过技术评审 - 所有依赖通过 vcpkg / Conan 管理禁止手动拷贝源码4.3 代码审查检查清单## Review 检查项 Claude 在生成代码后请自查以下项目 1. 是否使用了项目允许的 C 标准特性 2. 是否存在裸 new / delete 3. 所有权语义是否清晰谁创建、谁销毁 4. 是否有潜在的循环引用shared_ptr 互相持有 5. 是否引入了未批准的第三方依赖5. 完整 CLAUDE.md 配置示例下面是一份可以直接用在 C 项目中的完整配置你可以根据团队实际情况裁剪# CLAUDE.md — C Project Constitution 项目简介 本项目是一个高性能 C 网络服务框架服务于公司核心业务。 C 标准 核心标准C17 禁止使用 C20/23 特性Concepts、Ranges、Coroutines、std::span、三路比较 允许的 C17 特性if constexpr、结构化绑定、std::optional、std::variant、std::string_view、折叠表达式 内存管理 禁止使用裸 new / delete与 C 接口交互除外 统一使用 std::make_unique / std::make_shared 创建堆对象 函数参数语义 所有权转移 → std::unique_ptrlt;Tgt; 按值 只读访问 → const Tamp; 或 const T* 可选修改 → T*不转移所有权 禁止返回指向堆对象的裸指针 用 std::weak_ptr 打破循环引用 编译与工具链 编译器GCC 11 / Clang 14 CMake ≥ 3.20 编译选项-Wall -Wextra -Wpedantic -Werror 开发环境启用 ASan 依赖管理 vcpkg 统一管理依赖 白名单Boostasio/beast、fmtlib/fmt、Google Test、spdlog 禁止未经评审引入新依赖 代码风格 遵循 Google C Style Guide 命名规范类名 PascalCase、函数名 snake_case、成员变量后置下划线 value_ 头文件使用 #pragma once 禁止 using namespace 在头文件的全局作用域 审查自查 生成代码后自查标准合规、内存安全、所有权清晰、无未授权依赖。6. 实际效果一个对比案例如果没有CLAUDE.md当你对 Claude Code 说「写一个 TCP 连接管理器」它可能会生成这样的代码// 没有规则的产物不推荐 class Connection { Socket* socket_; // 裸指针所有权不明确 public: explicit Connection(Socket* s) : socket_(s) {} ~Connection() { delete socket_; } // 删除的是自己创建的吗 };有了CLAUDE.md约束后同样的指令会生成// 受 CLAUDE.md 约束的产物推荐 class Connection { std::unique_ptrSocket socket_; // 独占所有权语义清晰 public: explicit Connection(std::unique_ptrSocket socket) : socket_(std::move(socket)) {} // 析构函数自动释放无需手动 delete };后者不仅避免了手动delete还通过unique_ptr明确表达了「Connection 独占 Socket 所有权」的语义——这正是CLAUDE.md的核心价值让 AI 产出的代码天然符合团队规范而不是事后修补。7. 进阶技巧7.1 分模块定规则大型项目中不同子模块可能有不同约束。你可以在子目录下放置独立的CLAUDE.md# src/legacy/CLAUDE.md 本目录为遗留代码使用 C14 标准内存管理沿用裸指针 引用计数模式。 修改时请保持与现有代码风格一致不要引入智能指针。Claude Code 会自动加载当前工作目录下最近的CLAUDE.md子目录规则会覆盖根目录规则。7.2 借助 Git Hook 自动校验CLAUDE.md约束的是 AI 生成阶段但你还可以搭配clang-tidy或自定义脚本在提交阶段做二次校验。把校验规则写进CLAUDE.mdAI 在生成代码时会主动考虑这些检查项## CI 校验规则代码生成时必须满足 - clang-tidy 检查modernize-*, cppcoreguidelines-*, bugprone-* - 自定义检查代码中不得出现 new 或 delete 关键字 - 所有类必须具有明确的拷贝/移动语义声明 default / delete7.3 与 .clang-format 配合CLAUDE.md中声明格式化规范配合.clang-format文件实现自动格式化同时也让 AI 知道你的排版偏好## 格式化 - 使用项目根目录的 .clang-format 配置 - 缩进4 空格不使用 Tab - 行宽限制120 字符 - 大括号风格Attach不另起一行总结CLAUDE.md之于 Claude Code就像CMakeLists.txt之于构建系统、「编码规范文档」之于团队协作——它是 AI 编程助手的规则锚点。对于 C 项目锁定标准版本可以避免生成不兼容的语法明确内存管理规范能从源头减少内存 Bug。两个约束叠加起来让 AI 真正成为团队风格一致的协作者而不是一个需要你反复纠正的「自由创作者」。建议你现在就在项目根目录下创建CLAUDE.md先把 C 标准和内存规范写进去后续再根据团队反馈逐步迭代。毕竟好的规则不是一次写成的而是在实践中打磨出来的。