C++ Coding Standards (C++ Core Guidelines)
Comprehensive coding standards for modern C++ (C++17/20/23) derived from the C++ Core Guidelines. Enforces type safety, resource safety, immutability, and clarity.
When to Use
- Writing new C++ code (classes, functions, templates)
- Reviewing or refactoring existing C++ code
- Making architectural decisions in C++ projects
- Enforcing consistent style across a C++ codebase
- Choosing between language features (e.g.,
enumvsenum class, raw pointer vs smart pointer)
When NOT to Use
- Non-C++ projects
- Legacy C codebases that cannot adopt modern C++ features
- Embedded/bare-metal contexts where specific guidelines conflict with hardware constraints (adapt selectively)
Cross-Cutting Principles
These themes recur across the entire guidelines and form the foundation:
- RAII everywhere (P.8, R.1, E.6, CP.20): Bind resource lifetime to object lifetime
- Immutability by default (P.10, Con.1-5, ES.25): Start with
const/constexpr; mutability is the exception - Type safety (P.4, I.4, ES.46-49, Enum.3): Use the type system to prevent errors at compile time
- Express intent (P.3, F.1, NL.1-2, T.10): Names, types, and concepts should communicate purpose
- Minimize complexity (F.2-3, ES.5, Per.4-5): Simple code is correct code
- Value semantics over pointer semantics (C.10, R.3-5, F.20, CP.31): Prefer returning by value and scoped objects
Philosophy & Interfaces (P., I.)
Key Rules
DO
DON'T
Functions (F.*)
Key Rules
Parameter Passing
Pure Functions and constexpr
Anti-Patterns
- Returning
T&&from functions (F.45) - Using
va_arg/ C-style variadics (F.55) - Capturing by reference in lambdas passed to other threads (F.53)
- Returning
const Twhich inhibits move semantics (F.49)
Classes & Class Hierarchies (C.*)
Key Rules
Rule of Zero
Rule of Five
Class Hierarchy
Anti-Patterns
- Calling virtual functions in constructors/destructors (C.82)
- Using
memset/memcpyon non-trivial types (C.90) - Providing different default arguments for virtual function and overrider (C.140)
- Making data members
constor references, which suppresses move/copy (C.12)
Resource Management (R.*)
Key Rules
Smart Pointer Usage
RAII Pattern
Anti-Patterns
- Naked
new/delete(R.11) malloc()/free()in C++ code (R.10)- Multiple resource allocations in a single expression (R.13 -- exception safety hazard)
shared_ptrwhereunique_ptrsuffices (R.21)
Expressions & Statements (ES.*)
Key Rules
Initialization
Anti-Patterns
- Uninitialized variables (ES.20)
- Using
0orNULLas pointer (ES.47 -- usenullptr) - C-style casts (ES.48 -- use
static_cast,const_cast, etc.) - Casting away
const(ES.50) - Magic numbers without named constants (ES.45)
- Mixing signed and unsigned arithmetic (ES.100)
- Reusing names in nested scopes (ES.12)
Error Handling (E.*)
Key Rules
Exception Hierarchy
Anti-Patterns
- Throwing built-in types like
intor string literals (E.14) - Catching by value (slicing risk) (E.15)
- Empty catch blocks that silently swallow errors
- Using exceptions for flow control (E.3)
- Error handling based on global state like
errno(E.28)
Constants & Immutability (Con.*)
All Rules
Concurrency & Parallelism (CP.*)
Key Rules
Safe Locking
Multiple Mutexes
Anti-Patterns
volatilefor synchronization (CP.8 -- it's for hardware I/O only)- Detaching threads (CP.26 -- lifetime management becomes nearly impossible)
- Unnamed lock guards:
std::lock_guard<std::mutex>(m);destroys immediately (CP.44) - Holding locks while calling callbacks (CP.22 -- deadlock risk)
- Lock-free programming without deep expertise (CP.100)
Templates & Generic Programming (T.*)
Key Rules
Concepts (C++20)
Anti-Patterns
- Unconstrained templates in visible namespaces (T.47)
- Specializing function templates instead of overloading (T.144)
- Template metaprogramming where
constexprsuffices (T.120) typedefinstead ofusing(T.43)
Standard Library (SL.*)
Key Rules
Enumerations (Enum.*)
Key Rules
Source Files & Naming (SF., NL.)
Key Rules
Header Guard
Naming Conventions
Anti-Patterns
using namespace std;in a header at global scope (SF.7)- Headers that depend on inclusion order (SF.10, SF.11)
- Hungarian notation like
strName,iCount(NL.5) - ALL_CAPS for anything other than macros (NL.9)
Performance (Per.*)
Key Rules
Guidelines
Anti-Patterns
- Optimizing without profiling data (Per.1, Per.6)
- Choosing "clever" low-level code over clear abstractions (Per.4, Per.5)
- Ignoring data layout and cache behavior (Per.19)
Quick Reference Checklist
Before marking C++ work complete:
- No raw
new/delete-- use smart pointers or RAII (R.11) - Objects initialized at declaration (ES.20)
- Variables are
const/constexprby default (Con.1, ES.25) - Member functions are
constwhere possible (Con.2) -
enum classinstead of plainenum(Enum.3) -
nullptrinstead of0/NULL(ES.47) - No narrowing conversions (ES.46)
- No C-style casts (ES.48)
- Single-argument constructors are
explicit(C.46) - Rule of Zero or Rule of Five applied (C.20, C.21)
- Base class destructors are public virtual or protected non-virtual (C.35)
- Templates are constrained with concepts (T.10)
- No
using namespacein headers at global scope (SF.7) - Headers have include guards and are self-contained (SF.8, SF.11)
- Locks use RAII (
scoped_lock/lock_guard) (CP.20) - Exceptions are custom types, thrown by value, caught by reference (E.14, E.15)
-
'\n'instead ofstd::endl(SL.io.50) - No magic numbers (ES.45)

