Communitygithub.com

C++ 編碼標準 (C++ Core Guidelines)

基於 C++ Core Guidelines (isocpp.github.io) 的 C++ 編碼標準。在編寫、審查或重構 C++ 程式碼時使用,以強制執行現代、安全且慣用的做法。

C++ 編碼標準 (C++ Core Guidelines) 是什麼?

這個技能提供了從 C++ Core Guidelines 衍生出的全面性 C++ 編碼標準,涵蓋 C++17/20/23。它是一套嚴格的規則與最佳實踐,旨在強制執行型別安全、資源安全、不可變性和程式碼清晰度。該技能針對開發者編寫新 C++ 類別、函式與範本、審查或重構既有程式碼,以及建立架構決策等場景。其主要原則包含 RAII(資源獲取即初始化)、預設不可變性、靜態型別安全、表達意圖、最小化複雜度,以及偏好值語意而非指標語意。這項技能透過強制遵循特定規則,幫助開發者避免裸指針、C-style 轉型、未初始化變數與不必要的堆積分配等常見反模式。它特別支援根據 P.* 和 I.* 規則設計清晰介面、根據 F.* 規則編寫純函式與 constexpr 函式、根據 R.* 規則進行資源管理、根據 C.* 規則建立類別與類別階層,以及根據 ES.* 和 Con.* 規則進行安全表示式與常數處理。對於原則無法完整適用的舊式 C 程式碼庫或嵌入式平台,此技能也提供了明確的界限。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/cpp-coding-standards

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

C++ 編碼標準 (C++ Core Guidelines) 是做什麼的?

適用於現代 C++ (C++17/20/23) 的全方位編碼標準,衍生自 C++ Core Guidelines。強制執行型別安全、資源安全、不可變性與清晰度。

使用時機

  • 編寫新的 C++ 程式碼(類別、函式、範本)
  • 審查或重構現有的 C++ 程式碼
  • 在 C++ 專案中做出架構決策
  • 在整個 C++ 程式碼庫中強制執行一致的風格
  • 在語言特性之間做選擇(例如 enum vs enum class、裸指針 vs 智慧指針)

何時不應使用

  • 非 C++ 專案
  • 無法採用現代 C++ 功能的舊式 C 程式碼庫
  • 特定規範與硬體限制衝突的嵌入式/裸機環境(請因地制宜地調整)

跨領域原則

以下主題貫穿整個指南,構成其基礎:

  1. 隨處使用 RAII (P.8, R.1, E.6, CP.20):將資源生命週期綁定到物件生命週期
  2. 預設使用不可變性 (P.10, Con.1-5, ES.25):從 const/constexpr 開始;可變性是例外
  3. 型別安全 (P.4, I.4, ES.46-49, Enum.3):使用型別系統在編譯時防止錯誤
  4. 表達意圖 (P.3, F.1, NL.1-2, T.10):名稱、型別和概念應傳達目的
  5. 最小化複雜度 (F.2-3, ES.5, Per.4-5):簡單的程式碼就是正確的程式碼
  6. 值語意優先於指針語意 (C.10, R.3-5, F.20, CP.31):偏好按值返回和作用域物件

哲學與介面 (P., I.)

關鍵規則

規則摘要
P.1直接在程式碼中表達想法
P.3表達意圖
P.4理想上,程式應是靜態型別安全的
P.5偏好編譯期檢查勝過執行期檢查
P.8不要洩漏任何資源
P.10偏好不可變資料勝過可變資料
I.1讓介面明確
I.2避免非 const 的全域變數
I.4讓介面精確且強型別化
I.11永遠不要透過裸指針或引用轉移所有權
I.23保持函式參數數量精簡

正確作法

// P.10 + I.4:不可變、強型別的介面
struct Temperature {
    double kelvin;
};

Temperature boil(const Temperature& water);

錯誤作法

// 弱介面:所有權不明確、單位不明確
double boil(double* temp);

// 非 const 全域變數
int g_counter = 0;  // I.2 違規

函式 (F.*)

關鍵規則

規則摘要
F.1將有意義的操作封裝為精心命名的函式
F.2一個函式應執行單一邏輯操作
F.3保持函式簡短且簡單
F.4如果一個函式可能於編譯期求值,將其宣告為 constexpr
F.6如果你的函式一定不會拋出例外,將其宣告為 noexcept
F.8偏好純函式
F.16對於「輸入」參數,將低成本複製的型別按值傳遞,其他則透過 const& 傳遞
F.20對於「輸出」值,偏好使用回傳值而非輸出參數
F.21要回傳多個「輸出」值時,偏好回傳一個結構體
F.43永遠不要回傳指向區域物件的指標或引用

參數傳遞

// F.16:低成本型別按值傳遞,其他按 const&
void print(int x);                           // 便宜:按值
void analyze(const std::string& data);       // 昂貴:按 const&
void transform(std::string s);               // 接收端:按值(將會移動)

// F.20 + F.21:回傳值,而非輸出參數
struct ParseResult {
    std::string token;
    int position;
};

ParseResult parse(std::string_view input);   // 好:回傳結構體

// 不好:輸出參數
void parse(std::string_view input,
           std::string& token, int& pos);    // 避免這種寫法

純函式與 constexpr

// F.4 + F.8:純函式,可能的情況下使用 constexpr
constexpr int factorial(int n) noexcept {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

static_assert(factorial(5) == 120);

反模式

  • 從函式回傳 T&& (F.45)
  • 使用 va_arg / C-style 可變參數 (F.55)
  • 在傳遞給其他執行緒的 lambda 中按引用捕獲 (F.53)
  • 回傳 const T 會抑制移動語意 (F.49)

類別與類別階層 (C.*)

關鍵規則

規則摘要
C.2如果存在不變量,使用 class;如果資料成員獨立變化,使用 struct
C.9最小化成員的暴露程度
C.20如果可以避免定義預設操作,就這麼做(零規則)
C.21如果你定義或 =delete 任何複製/移動/解構子,則需處理它們全部(五規則)
C.35基底類別解構子應為 public virtual 或 protected non-virtual
C.41建構子應建立一個完全初始化的物件
C.46宣告單一參數的建構子為 explicit
C.67多型類別應抑制 public 的複製/移動
C.128虛擬函式:精確指定 virtual、override 或 final 其中之一

零規則

// C.20:讓編譯器產生特殊成員
struct Employee {
    std::string name;
    std::string department;
    int id;
    // 不需要解構子、複製/移動建構子或賦值運算子
};

五規則

// C.21:如果你必須管理一個資源,定義全部五個
class Buffer {
public:
    explicit Buffer(std::size_t size)
        : data_(std::make_unique<char[]>(size)), size_(size) {}

    ~Buffer() = default;

    Buffer(const Buffer& other)
        : data_(std::make_unique<char[]>(other.size_)), size_(other.size_) {
        std::copy_n(other.data_.get(), size_, data_.get());
    }

    Buffer& operator=(const Buffer& other) {
        if (this != &other) {
            auto new_data = std::make_unique<char[]>(other.size_);
            std::copy_n(other.data_.get(), other.size_, new_data.get());
            data_ = std::move(new_data);
            size_ = other.size_;
        }
        return *this;
    }

    Buffer(Buffer&&) noexcept = default;
    Buffer& operator=(Buffer&&) noexcept = default;

private:
    std::unique_ptr<char[]> data_;
    std::size_t size_;
};

類別階層

// C.35 + C.128:虛擬解構子,使用 override
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;  // C.121:純粹介面
};

class Circle : public Shape {
public:
    explicit Circle(double r) : radius_(r) {}
    double area() const override { return 3.14159 * radius_ * radius_; }

private:
    double radius_;
};

反模式

  • 在建構子/解構子中呼叫虛擬函式 (C.82)
  • 在非平凡型別上使用 memset/memcpy (C.90)
  • 為虛擬函式及其覆寫版本提供不同的預設引數 (C.140)
  • 將資料成員設為 const 或引用,這會抑制移動/複製 (C.12)

資源管理 (R.*)

關鍵規則

規則摘要
R.1使用 RAII 自動管理資源
R.3裸指針 (T*) 是非擁有的
R.5偏好作用域物件;不要進行不必要的堆積分配
R.10避免使用 malloc()/free()
R.11避免顯式呼叫 new 和 delete
R.20使用 unique_ptr 或 shared_ptr 來表示所有權
R.21偏好 unique_ptr 勝過 shared_ptr,除非需要共享所有權
R.22使用 make_shared() 來建立 shared_ptr

智慧指針用法

// R.11 + R.20 + R.21:使用 RAII 和智慧指針
auto widget = std::make_unique<Widget>("config");  // 唯一所有權
auto cache  = std::make_shared<Cache>(1024);        // 共享所有權

// R.3:裸指針 = 非擁有觀察者
void render(const Widget* w) {  // 不擁有 w
    if (w) w->draw();
}

render(widget.get());

RAII 模式

// R.1:資源獲取即初始化
class FileHandle {
public:
    explicit FileHandle(const std::string& path)
        : handle_(std::fopen(path.c_str(), "r")) {
        if (!handle_) throw std::runtime_error("無法開啟: " + path);
    }

    ~FileHandle() {
        if (handle_) std::fclose(handle_);
    }

    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;
    FileHandle(FileHandle&& other) noexcept
        : handle_(std::exchange(other.handle_, nullptr)) {}
    FileHandle& operator=(FileHandle&& other) noexcept {
        if (this != &other) {
            if (handle_) std::fclose(handle_);
            handle_ = std::exchange(other.handle_, nullptr);
        }
        return *this;
    }

private:
    std::FILE* handle_;
};

反模式

  • 裸 new/delete (R.11)
  • 在 C++ 程式碼中使用 malloc()/free() (R.10)
  • 在單一表達式中進行多次資源分配 (R.13 -- 例外安全危害)
  • 在 unique_ptr 足以勝任時使用 shared_ptr (R.21)

表達式與陳述式 (ES.*)

關鍵規則

規則摘要
ES.5保持作用域小
ES.20永遠初始化一個物件
ES.23偏好 {} 初始化語法
ES.25除非意圖修改,否則將物件宣告為 const 或 constexpr
ES.28對於 const 變數的複雜初始化,使用 lambda
ES.45避免魔術常量;使用符號常量
ES.46避免窄化/有損耗的算術轉換
ES.47使用 nullptr 而非 0 或 NULL
ES.48避免轉型
ES.50不要強行去除 const

初始化

// ES.20 + ES.23 + ES.25:永遠初始化,偏好 {},預設為 const
const int max_retries{3};
const std::string name{"widget"};
const std::vector<int> primes{2, 3, 5, 7, 11};

// ES.28:用 lambda 進行複雜的 const 初始化
const auto config = [&] {
    Config c;
    c.timeout = std::chrono::seconds{30};
    c.retries = max_retries;
    c.verbose = debug_mode;
    return c;
}();

反模式

  • 未初始化的變數 (ES.20)
  • 使用 0 或 NULL 作為指針 (ES.47 -- 使用 nullptr)
  • C-style 轉型 (ES.48 -- 使用 static_cast、const_cast 等)
  • 強行去除 const (ES.50)
  • 沒有命名常量的魔術數字 (ES.45)
  • 混用有號數和無號數算術 (ES.100)
  • 在巢狀作用域中重用名稱 (ES.12)

錯誤處理 (E.*)

關鍵規則

規則摘要
E.1在設計早期就制定錯誤處理策略
E.2拋出例外以表示函式無法執行其指定任務
E.6使用 RAII 來防止資源洩漏
E.12當不可能或不允許拋出時使用 noexcept
E.14使用專門設計的使用者自訂型別作為例外
E.15按值拋出,按引用捕獲
E.16解構子、解分配和 swap 絕不能失敗
E.17不要試圖在每個函式中捕獲每個例外

例外階層

// E.14 + E.15:自訂例外型別,按值拋出,按引用捕獲
class AppError : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
};

class NetworkError : public AppError {
public:
    NetworkError(const std::string& msg, int code)
        : AppError(msg), status_code(code) {}
    int status_code;
};

void fetch_data(const std::string& url) {
    // E.2:拋出以表示失敗
    throw NetworkError("連線被拒絕", 503);
}

void run() {
    try {
        fetch_data("https://api.example.com");
    } catch (const NetworkError& e) {
        log_error(e.what(), e.status_code);
    } catch (const AppError& e) {
        log_error(e.what());
    }
    // E.17:不要在這裡捕獲所有東西 -- 讓未預期的錯誤傳播出去
}

反模式

  • 拋出內建型別如 int 或字串字面量 (E.14)
  • 按值捕獲(有切片風險)(E.15)
  • 默默吞噬錯誤的空捕獲區塊
  • 使用例外進行流程控制 (E.3)
  • 基於像 errno 這樣的全域狀態進行錯誤處理 (E.28)

常量與不可變性 (Con.*)

所有規則

規則摘要
Con.1預設情況下,使物件不可變
Con.2預設情況下,使成員函式為 const
Con.3預設情況下,傳遞指標和引用時使用 const
Con.4對建構後不會變更的值使用 const
Con.5對可在編譯期計算的值使用 constexpr
// Con.1 到 Con.5:預設使用不可變性
class Sensor {
public:
    explicit Sensor(std::string id) : id_(std::move(id)) {}

    // Con.2:預設使用 const 成員函式
    const std::string& id() const { return id_; }
    double last_reading() const { return reading_; }

    // 僅在需要修改時才為非 const
    void record(double value) { reading_ = value; }

private:
    const std::string id_;  // Con.4:建構後永不改變
    double reading_{0.0};
};

// Con.3:按 const 引用傳遞
void display(const Sensor& s) {
    std::cout << s.id() << ": " << s.last_reading() << '\n';
}

// Con.5:編譯期常量
constexpr double PI = 3.14159265358979;
constexpr int MAX_SENSORS = 256;

並行與平行處理 (CP.*)

關鍵規則

規則摘要
CP.2避免資料競爭
CP.3最小化可寫入資料的顯式共享
CP.4以任務而非執行緒的角度思考
CP.8不要使用 volatile 進行同步
CP.20使用 RAII,永遠不要使用裸 lock()/unlock()
CP.21使用 std::scoped_lock 來獲取多個互斥鎖
CP.22持有鎖時絕不呼叫未知程式碼
CP.42不要無條件地等待
CP.44記得為你的 lock_guards 和 unique_locks 命名
CP.100除非絕對必要,否則不要使用無鎖編程

安全的鎖定

// CP.20 + CP.44:RAII 鎖,務必命名
class ThreadSafeQueue {
public:
    void push(int value

…

[為翻譯而截斷]

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相關技能