Communitygithub.com

C++ 코딩 표준 (C++ 코어 가이드라인)

C++ 코어 가이드라인(isocpp.github.io)에 기반한 C++ 코딩 표준입니다. 현대적이고 안전하며 관용적인 C++ 코드를 작성, 검토, 리팩터링할 때 사용하여 모범 사례를 강제합니다.

C++ 코딩 표준 (C++ 코어 가이드라인)란 무엇인가요?

이 스킬은 C++ 코어 가이드라인에서 파생된 포괄적인 C++ 코딩 표준을 제공합니다. C++17/20/23을 대상으로 하며 타입 안전성, 리소스 안전성, 불변성, 코드 명확성을 강제합니다. 새로운 C++ 코드를 작성하거나 기존 코드를 리뷰 및 리팩터링할 때, 또는 C++ 프로젝트에서 아키텍처 결정을 내릴 때 유용합니다. RAII, 불변성 우선, 타입 안전성, 의도 표현, 복잡성 최소화, 값 의미론 등의 핵심 원칙을 따르며, 각 주제별(철학, 함수, 클래스, 리소스 관리, 표현식, 오류 처리, 상수, 동시성)로 주요 규칙, 모범 사례 코드 예제, 안티 패턴을 포함합니다. 이 가이드라인은 모든 C++ 코드베이스에 일관된 스타일을 적용하고 최신 언어 기능을 올바르게 사용하도록 돕습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/cpp-coding-standards

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

C++ 코딩 표준 (C++ 코어 가이드라인)은(는) 무엇을 하나요?

C++ 코어 가이드라인에서 파생된 현대 C++(C++17/20/23)용 포괄적 코딩 표준입니다. 타입 안전성, 리소스 안전성, 불변성, 명확성을 강제합니다.

사용 시기

  • 새 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"in" 매개변수의 경우 저렴하게 복사되는 타입은 값으로, 나머지는 const&로 전달
F.20"out" 값의 경우 출력 매개변수보다 반환 값 선호
F.21여러 "out" 값을 반환하려면 구조체 반환 선호
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 스타일 가변 인자 사용 (F.55)
  • 다른 스레드로 전달되는 람다에서 참조 캡처 (F.53)
  • 이동 의미론을 억제하는 const T 반환 (F.49)

클래스 및 클래스 계층 구조 (C.*)

주요 규칙

규칙요약
C.2불변 조건이 있으면 class 사용; 데이터 멤버가 독립적으로 변하면 struct 사용
C.9멤버 노출 최소화
C.20기본 연산을 정의하지 않아도 되면 그러지 마세요 (0의 규칙)
C.21복사/이동/소멸자를 정의하거나 =delete하면 모두 처리하세요 (5의 규칙)
C.35기반 클래스 소멸자: public virtual 또는 protected non-virtual
C.41생성자는 완전히 초기화된 객체를 생성해야 함
C.46단일 인자 생성자는 explicit으로 선언
C.67다형성 클래스는 public 복사/이동을 억제해야 함
C.128가상 함수: virtual, override, final 중 정확히 하나만 지정

0의 규칙

// C.20: 컴파일러가 특수 멤버를 생성하도록 함
struct Employee {
    std::string name;
    std::string department;
    int id;
    // 소멸자, 복사/이동 생성자, 할당 연산자 필요 없음
};

5의 규칙

// 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.1RAII를 사용하여 리소스를 자동으로 관리
R.3원시 포인터(T*)는 소유하지 않음
R.5범위 객체 선호; 불필요하게 힙 할당하지 마세요
R.10malloc()/free() 피하기
R.11명시적으로 new와 delete 호출 피하기
R.20소유권을 나타내려면 unique_ptr 또는 shared_ptr 사용
R.21소유권을 공유하지 않는 한 shared_ptr보다 unique_ptr 선호
R.22shared_ptr을 만들려면 make_shared() 사용

스마트 포인터 사용

// 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("Failed to open: " + 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.28const 변수의 복잡한 초기화에는 람다 사용
ES.45매직 상수 피하기; 기호 상수 사용
ES.46축소/손실 산술 변환 피하기
ES.470이나 NULL 대신 nullptr 사용
ES.48캐스트 피하기
ES.50const를 캐스트하여 제거하지 마세요

초기화

// 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: 복잡한 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 스타일 캐스트 (ES.48 -- static_cast, const_cast 등 사용)
  • const 캐스트하여 제거 (ES.50)
  • 이름 있는 상수 없는 매직 넘버 (ES.45)
  • 부호 있는 정수와 부호 없는 정수 혼합 (ES.100)
  • 중첩 범위에서 이름 재사용 (ES.12)

오류 처리 (E.*)

주요 규칙

규칙요약
E.1설계 초기에 오류 처리 전략 개발
E.2함수가 할당된 작업을 수행할 수 없음을 알리려면 예외 던지기
E.6RAII를 사용하여 누출 방지
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("connection refused", 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)
  • 오류를 조용히 삼키는 빈 catch 블록
  • 흐름 제어에 예외 사용 (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.20RAII 사용, 절대 lock()/unlock() 직접 사용하지 마세요
CP.21여러 뮤텍스 획득에 std::scoped_lock 사용
CP.22락을 보유한 상태에서 알 수 없는 코드를 절대 호출하지 마세요
CP.42조건 없이 기다리지 마세요
CP.44lock_guard와 unique_lock의 이름을 지정하는 것을 기억하세요
CP.100절대적으로 필요하지 않으면 락-프리 프로그래밍을 사용하지 마세요

안전한 락킹

// CP.20 + CP.44: RAII 락, 항상 이름 지정
class ThreadSafeQueue {
public:
    void push(int value) {
        std::lock_guard<std::mutex> lock(mutex_); // CP.20: RAII, CP.44: 이름 지정
        queue_.push(value);
    }

    int pop() {
        std::lock_guard<std::mutex> lock(mutex_);
        if (queue_.empty()) throw std::runtime_error("queue is empty");
        int value = queue_.front();
        queue_.pop();
        return value;
    }

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

안티 패턴

  • 락 없이 공유 데이터에 접근 (CP.2)
  • 락 걸기 전에 알 수 없는 사용자 코드 호출 (CP.22)
  • 조건 변수 없이 스핀 대기 (CP.42)
  • std::lock() 대신 여러 중첩된 lock() 호출 사용
  • 락-프리 기법을 간단한 뮤텍스보다 먼저 고려

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/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

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.

관련 스킬