Communitygithub.com

C++-Programmierstandards (C++ Core Guidelines)

C++-Programmierstandards basierend auf den C++ Core Guidelines (isocpp.github.io). Verwenden Sie diese beim Schreiben, Überprüfen oder Refaktorieren von C++-Code, um moderne, sichere und idiomatische Praktiken durchzusetzen.

Was ist C++-Programmierstandards (C++ Core Guidelines)?

Diese Fähigkeit definiert umfassende Programmierstandards für modernes C++ (C++17/20/23), die von den offiziellen C++ Core Guidelines abgeleitet sind. Sie ist für Entwickler und KI-Agenten konzipiert, die C++-Code schreiben, überprüfen oder umgestalten. Die Fähigkeit hilft, moderne Best Practices wie Typsicherheit, Ressourcensicherheit (RAII), Unveränderlichkeit (const/costexpr) und Klarheit durchzusetzen. Sie unterstützt Codegenerierung, Code-Review und Refactoring-Ergebnisse in allen gängigen Entwicklungsplattformen wie Claude Code, Cursor oder Codex, indem sie detaillierte Regeln und konkrete Beispiele für und gegen antipatterns für Klassen, Funktionen, Ressourcenverwaltung, Ausdrücke, Fehlerbehandlung, Konstanten und Parallelität liefert. Die dokumentierten Regeln stammen direkt aus den C++ Core Guidelines und enthalten prägnante Zusammenfassungen, Codebeispiele und Abschnitte zu Anti-Patterns, die Entwickler oder KI-Agenten als Referenz nutzen können.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht C++-Programmierstandards (C++ Core Guidelines)?

Umfassende Programmierstandards für modernes C++ (C++17/20/23) abgeleitet von den C++ Core Guidelines. Setzt Typsicherheit, Ressourcensicherheit, Unveränderlichkeit und Klarheit durch.

Wann verwenden

  • Schreiben von neuem C++-Code (Klassen, Funktionen, Templates)
  • Überprüfen oder Refaktorieren von vorhandenem C++-Code
  • Treffen von Architekturentscheidungen in C++-Projekten
  • Durchsetzen eines konsistenten Stils über eine C++-Codebasis hinweg
  • Wahl zwischen Sprachfeatures (z. B. enum vs enum class, Raw Pointer vs Smart Pointer)

Wann NICHT verwenden

  • Nicht-C++-Projekte
  • Legacy-C-Codebasen, die keine modernen C++-Features übernehmen können
  • Eingebettete/Bare-Metal-Kontexte, in denen spezifische Richtlinien mit Hardware-Beschränkungen kollidieren (selektiv anpassen)

Querschnittsprinzipien

Diese Themen ziehen sich durch die gesamten Richtlinien und bilden die Grundlage:

  1. RAII überall (P.8, R.1, E.6, CP.20): Ressourcenlebensdauer an Objektlebensdauer binden
  2. Unveränderlichkeit als Standard (P.10, Con.1-5, ES.25): Beginnen Sie mit const/constexpr; Veränderlichkeit ist die Ausnahme
  3. Typsicherheit (P.4, I.4, ES.46-49, Enum.3): Verwenden Sie das Typsystem, um Fehler zur Kompilierzeit zu verhindern
  4. Absicht ausdrücken (P.3, F.1, NL.1-2, T.10): Namen, Typen und Konzepte sollten Zweck kommunizieren
  5. Komplexität minimieren (F.2-3, ES.5, Per.4-5): Einfacher Code ist korrekter Code
  6. Wertsemantik vor Zeigersemantik (C.10, R.3-5, F.20, CP.31): Bevorzugen Sie Rückgabe nach Wert und Objekte im Gültigkeitsbereich

Philosophie & Schnittstellen (P., I.)

Wichtige Regeln

RegelZusammenfassung
P.1Ideen direkt im Code ausdrücken
P.3Absicht ausdrücken
P.4Idealerweise sollte ein Programm statisch typischer sein
P.5Kompilierzeit-Prüfung vor Laufzeit-Prüfung bevorzugen
P.8Keine Ressourcen durchsickern lassen
P.10Unveränderliche Daten veränderlichen vorziehen
I.1Schnittstellen explizit machen
I.2Nicht-konstante globale Variablen vermeiden
I.4Schnittstellen präzise und stark typisiert machen
I.11Besitz niemals über einen Raw Pointer oder eine Referenz übergeben
I.23Anzahl der Funktionsargumente gering halten

RICHTIG

// P.10 + I.4: Unveränderliche, stark typisierte Schnittstelle
struct Temperature {
    double kelvin;
};

Temperature boil(const Temperature& water);

FALSCH

// Schwache Schnittstelle: unklarer Besitz, unklare Einheiten
double boil(double* temp);

// Nicht-konstante globale Variable
int g_counter = 0;  // I.2-Verstoß

Funktionen (F.*)

Wichtige Regeln

RegelZusammenfassung
F.1Sinnvolle Operationen als sorgfältig benannte Funktionen kapseln
F.2Eine Funktion sollte eine einzige logische Operation ausführen
F.3Funktionen kurz und einfach halten
F.4Wenn eine Funktion zur Kompilierzeit ausgewertet werden könnte, deklarieren Sie sie constexpr
F.6Wenn Ihre Funktion nicht werfen darf, deklarieren Sie sie noexcept
F.8Reine Funktionen bevorzugen
F.16Für "Eingabe"-Parameter: günstig kopierbare Typen als Wert übergeben, andere als const&
F.20Für "Ausgabe"-Werte: Rückgabewerte Ausgabeparametern vorziehen
F.21Um mehrere "Ausgabe"-Werte zurückzugeben, ein Struktur zurückgeben bevorzugen
F.43Niemals einen Zeiger oder eine Referenz auf ein lokales Objekt zurückgeben

Parameterübergabe

// F.16: Günstige Typen als Wert, andere als const&
void print(int x);                           // günstig: als Wert
void analyze(const std::string& data);       // teuer: als const&
void transform(std::string s);               // Senke: als Wert (wird verschieben)

// F.20 + F.21: Rückgabewerte, nicht Ausgabeparameter
struct ParseResult {
    std::string token;
    int position;
};

ParseResult parse(std::string_view input);   // GUT: Struktur zurückgeben

// SCHLECHT: Ausgabeparameter
void parse(std::string_view input,
           std::string& token, int& pos);    // dies vermeiden

Reine Funktionen und constexpr

// F.4 + F.8: Rein, constexpr wo möglich
constexpr int factorial(int n) noexcept {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

static_assert(factorial(5) == 120);

Anti-Patterns

  • Rückgabe von T&& von Funktionen (F.45)
  • Verwendung von va_arg / C-artigen Variadics (F.55)
  • Erfassen per Referenz in Lambdas, die an andere Threads übergeben werden (F.53)
  • Rückgabe von const T, das Move-Semantik unterbindet (F.49)

Klassen & Klassenhierarchien (C.*)

Wichtige Regeln

RegelZusammenfassung
C.2class verwenden, wenn eine Invariante existiert; struct, wenn Datenelemente unabhängig variieren
C.9Offenlegung von Elementen minimieren
C.20Wenn Sie die Definition von Standardoperationen vermeiden können, tun Sie es (Null-Regel)
C.21Wenn Sie irgendeine Kopier-/Verschiebe-/Destruktor-Operation definieren oder =delete, behandeln Sie alle (Fünf-Regel)
C.35Basisklassendestruktor: öffentlich virtuell oder geschützt nicht-virtuell
C.41Ein Konstruktor sollte ein vollständig initialisiertes Objekt erzeugen
C.46Einparametrige Konstruktoren als explicit deklarieren
C.67Eine polymorphe Klasse sollte öffentliches Kopieren/Verschieben unterdrücken
C.128Virtuelle Funktionen: genau eines von virtual, override oder final angeben

Null-Regel

// C.20: Compiler generierte Spezialmitglieder
struct Employee {
    std::string name;
    std::string department;
    int id;
    // Kein Destruktor, keine Kopier-/Verschiebekonstruktoren oder Zuweisungsoperatoren erforderlich
};

Fünf-Regel

// C.21: Wenn Sie eine Ressource verwalten müssen, definieren Sie alle fünf
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_;
};

Klassenhierarchie

// C.35 + C.128: Virtueller Destruktor, override verwenden
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;  // C.121: reine Schnittstelle
};

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

private:
    double radius_;
};

Anti-Patterns

  • Aufrufen virtueller Funktionen in Konstruktoren/Destruktoren (C.82)
  • Verwendung von memset/memcpy auf nicht-triviale Typen (C.90)
  • Bereitstellen unterschiedlicher Standardargumente für virtuelle Funktion und Überschreibung (C.140)
  • Datenelemente als const oder Referenzen machen, was Verschieben/Kopieren unterbindet (C.12)

Ressourcenverwaltung (R.*)

Wichtige Regeln

RegelZusammenfassung
R.1Ressourcen automatisch mit RAII verwalten
R.3Ein Raw Pointer (T*) ist nicht besitzend
R.5Objekte im Gültigkeitsbereich bevorzugen; nicht unnötig auf dem Heap allozieren
R.10malloc()/free() vermeiden
R.11Explizites new und delete vermeiden
R.20unique_ptr oder shared_ptr verwenden, um Besitz darzustellen
R.21unique_ptr gegenüber shared_ptr bevorzugen, es sei denn, Besitz wird geteilt
R.22make_shared() verwenden, um shared_ptrs zu erstellen

Smart Pointer Verwendung

// R.11 + R.20 + R.21: RAII mit Smart Pointern
auto widget = std::make_unique<Widget>("config");  // eindeutiger Besitz
auto cache  = std::make_shared<Cache>(1024);        // geteilter Besitz

// R.3: Raw Pointer = nicht-besitzender Beobachter
void render(const Widget* w) {  // besitzt w NICHT
    if (w) w->draw();
}

render(widget.get());

RAII-Muster

// R.1: Ressourcenerwerb ist Initialisierung
class FileHandle {
public:
    explicit FileHandle(const std::string& path)
        : handle_(std::fopen(path.c_str(), "r")) {
        if (!handle_) throw std::runtime_error("Fehler beim Öffnen: " + 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_;
};

Anti-Patterns

  • Nacktes new/delete (R.11)
  • malloc()/free() in C++-Code (R.10)
  • Mehrere Ressourcenzuweisungen in einem einzelnen Ausdruck (R.13 -- Ausnahmesicherheitsgefahr)
  • shared_ptr, wo unique_ptr ausreicht (R.21)

Ausdrücke & Anweisungen (ES.*)

Wichtige Regeln

RegelZusammenfassung
ES.5Gültigkeitsbereiche klein halten
ES.20Ein Objekt immer initialisieren
ES.23{}-Initialisierungssyntax bevorzugen
ES.25Objekte als const oder constexpr deklarieren, es sei denn, Änderung ist beabsichtigt
ES.28Lambdas für komplexe Initialisierung von const-Variablen verwenden
ES.45Magische Konstanten vermeiden; symbolische Konstanten verwenden
ES.46Verengende/verlustbehaftete arithmetische Konvertierungen vermeiden
ES.47nullptr anstelle von 0 oder NULL verwenden
ES.48Casts vermeiden
ES.50const nicht wegcasten

Initialisierung

// ES.20 + ES.23 + ES.25: Immer initialisieren, {} bevorzugen, standardmäßig const
const int max_retries{3};
const std::string name{"widget"};
const std::vector<int> primes{2, 3, 5, 7, 11};

// ES.28: Lambda für komplexe const-Initialisierung
const auto config = [&] {
    Config c;
    c.timeout = std::chrono::seconds{30};
    c.retries = max_retries;
    c.verbose = debug_mode;
    return c;
}();

Anti-Patterns

  • Nicht initialisierte Variablen (ES.20)
  • Verwendung von 0 oder NULL als Zeiger (ES.47 -- nullptr verwenden)
  • C-artige Casts (ES.48 -- static_cast, const_cast usw. verwenden)
  • Wegcasten von const (ES.50)
  • Magische Zahlen ohne benannte Konstanten (ES.45)
  • Mischen von signed und unsigned Arithmetik (ES.100)
  • Wiederverwendung von Namen in verschachtelten Gültigkeitsbereichen (ES.12)

Fehlerbehandlung (E.*)

Wichtige Regeln

RegelZusammenfassung
E.1Frühzeitig eine Fehlerbehandlungsstrategie entwickeln
E.2Ausnahme werfen, um zu signalisieren, dass eine Funktion ihre zugewiesene Aufgabe nicht erfüllen kann
E.6RAII verwenden, um Lecks zu verhindern
E.12noexcept verwenden, wenn Werfen unmöglich oder inakzeptabel ist
E.14Zweckentworfene benutzerdefinierte Typen als Ausnahmen verwenden
E.15Als Wert werfen, per Referenz fangen
E.16Destruktoren, Freigabe und swap dürfen niemals fehlschlagen
E.17Nicht versuchen, jede Ausnahme in jeder Funktion zu fangen

Ausnahmehierarchie

// E.14 + E.15: Benutzerdefinierte Ausnahmetypen, als Wert werfen, per Referenz fangen
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: Werfen, um Fehler zu signalisieren
    throw NetworkError("Verbindung abgelehnt", 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: Hier nicht alles fangen -- unerwartete Fehler propagieren lassen
}

Anti-Patterns

  • Werfen von eingebauten Typen wie int oder Zeichenkettenliteralen (E.14)
  • Fangen als Wert (Slicing-Risiko) (E.15)
  • Leere catch-Blöcke, die Fehler stillschweigend verschlucken
  • Verwendung von Ausnahmen für die Kontrollflusssteuerung (E.3)
  • Fehlerbehandlung basierend auf globalem Zustand wie errno (E.28)

Konstanten & Unveränderlichkeit (Con.*)

Alle Regeln

RegelZusammenfassung
Con.1Standardmäßig Objekte unveränderlich machen
Con.2Standardmäßig Memberfunktionen const machen
Con.3Standardmäßig Zeiger und Referenzen auf const übergeben
Con.4const für Werte verwenden, die sich nach der Konstruktion nicht ändern
Con.5constexpr für Werte verwenden, die zur Kompilierzeit berechenbar sind
// Con.1 bis Con.5: Unveränderlichkeit als Standard
class Sensor {
public:
    explicit Sensor(std::string id) : id_(std::move(id)) {}

    // Con.2: Standardmäßig const-Memberfunktionen
    const std::string& id() const { return id_; }
    double last_reading() const { return reading_; }

    // Nur nicht-konst, wenn Mutation erforderlich ist
    void record(double value) { reading_ = value; }

private:
    const std::string id_;  // Con.4: ändert sich nach Konstruktion nie
    double reading_{0.0};
};

// Con.3: Per const-Referenz übergeben
void display(const Sensor& s) {
    std::cout << s.id() << ": " << s.last_reading() << '\n';
}

// Con.5: Kompilierzeitkonstanten
constexpr double PI = 3.14159265358979;
constexpr int MAX_SENSORS = 256;

Nebenläufigkeit & Parallelität (CP.*)

Wichtige Regeln

RegelZusammenfassung
CP.2Datenrennen vermeiden
CP.3Explizites Teilen von beschreibbaren Daten minimieren
CP.4In Aufgaben denken, nicht in Threads
CP.8volatile nicht für Synchronisation verwenden
CP.20RAII verwenden, niemals einfaches lock()/unlock()
CP.21std::scoped_lock verwenden, um mehrere Mutexe zu erwerben
CP.22Niemals unbekannten Code aufrufen, während ein Lock gehalten wird
CP.42Nicht ohne Bedingung warten
CP.44Denken Sie daran, Ihre lock_guards und unique_locks zu benennen
CP.100Lock-freie Programmierung nur verwenden, wenn es absolut notwendig ist

Sicheres Locking

// CP.20 + CP.44: RAII-Locks, immer benannt
class ThreadSafeQueue {
public:
    void push(int value) {
        std::scoped_lock lock(mutex_);  // CP.21: sicherer Erwerb mehrerer Mutexe
        queue_.push(value);
    }

    bool pop(int& value) {
        std::unique_lock lock(mutex_);  // CP.44: benannter Lock
        if (queue_.empty()) {
            return false;
        }
        value = queue_.front();
        queue_.pop();
        return true;
    }

private:
    std::mutex mutex_;
    std::queue<int> queue_;
};

Anti-Patterns

  • Manuelles lock()/unlock() (CP.20)
  • Halten eines Locks über einen Funktionsaufruf hinweg, der Locken erwerben könnte (CP.22)
  • Verwendung von volatile als Synchronisationsmechanismus (CP.8)
  • Unbedingtes Warten (CP.42)
  • Lock-freie Programmierung für komplexe gemeinsam genutzte Datenstrukturen (CP.100)

Quellen

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.

Verwandte Skills