모던 C++ 언어 기능
C++11부터 C++23까지의 기능을 문법 소개보다 "왜 이렇게 쓰는지"와 "어디서 틀리는지"에 무게를 두고 정리합니다. 이동 의미론과 값 카테고리, 람다 캡처, 템플릿 인자 추론, SFINAE와 Concepts, ranges·views가 중심입니다.
Rule of Five, RAII, CRTP, 타입 소거, Visitor 같은 설계 패턴과 객체 수명, 링키지, 헤더 가드처럼 코드 구조에 관한 글도 있습니다. 예제는 컴파일해서 확인했고, 환경이 다르면 결과가 달라질 수 있는 부분은 본문에 환경을 적었습니다.
처음 읽기 좋은 글
- C++ Move 시맨틱스: 복사와 이동의 차이, rvalue 참조, std::move
- C++ 값 카테고리: lvalue, prvalue, xvalue를 구분하는 기준
- C++17·20·23 주요 기능 정리: 구조화 바인딩부터 Concepts·Ranges·std::print까지
전체 글 97편
각 글에 표시된 난이도를 기준으로 초급, 중급, 고급 순으로 나눴습니다. 처음이라면 위쪽부터 읽고, 이미 아는 단계는 건너뛰어도 됩니다.
초급 (18편)
- #ifndef vs #pragma once: C++ 헤더 가드의 동작 원리와 선택 기준
- C++ 연산자 우선순위 함정: flags & MASK == 0 같은 비트·비교·논리 연산자 버그
- C++ 조건문: if/else/switch 사용법과 흔한 실수
- C++ 포인터 처음 배우기: &와 * 연산자, swap·배열 순회, 초보자가 하는 첫 실수
- C++ 함수 오버로딩: 오버로드 해석 순서와 모호한 호출이 생기는 경우
- C++ 함수 처음 만들기: 선언과 정의, 값·참조 전달, 오버로딩, 기본 인자 (예제 10개)
- C++ Adapter 패턴: 객체 어댑터 vs 클래스 어댑터로 레거시·외부 API 감싸기
- C++ C 배열 vs std::array vs vector: 성능과 안전성 비교
- C++ count·count_if와 all_of·any_of·none_of로 조건 집계하기
- C++ fill·generate·iota로 범위 채우기: 테스트 데이터 생성 예제
- C++ iostream 다루기: 포매팅 조작자, stringstream 파싱, cin 버퍼와 스트림 실패 상태
- C++ min·max·minmax_element와 std::clamp: 값 비교와 범위 제한
- C++ queue와 stack: 컨테이너 어댑터 사용법과 BFS·DFS 활용
- C++ sleep_for·sleep_until로 주기 작업 만들기: 누적 드리프트와 짧은 sleep의 부정확함
- C++ static 멤버 변수와 함수: 초기화 순서, 스레드 안전성, C++17 inline static
- C++ std::vector 기초: 생성·삽입·삭제와 배열 대신 쓰는 이유
- C++11 random 라이브러리: rand() % n이 편향되는 이유와 mt19937·분포 사용법
- C++17 구조적 바인딩: map·pair·tuple 분해와 auto&·const auto& 선택
중급 (45편)
- [[nodiscard]]로 반환값 무시 막기: 에러 코드, RAII 타입, 사유 메시지, Clang-Tidy 검증
- C++ = default와 = delete: 특수 멤버 함수 제어와 복사 금지·이동 전용 타입
- C++ 객체 수명과 저장 기간: 생성·소멸 순서, 임시 객체 수명, 댕글링 참조
- C++ 객체 슬라이싱: 파생 부분이 잘려 나가는 네 가지 경우와 다형성 지키는 법
- C++ 관찰 포인터: 소유하지 않는 참조를 원시 포인터·weak_ptr로 표현하는 기준
- C++ 바이너리 직렬화: 엔디안·구조체 패딩 문제와 버전 관리·체크섬
- C++ 반복자: 종류와 연산, iterator_traits, 범위 기반 for의 디슈가링
- C++ 복사 생성자와 이동 생성자: 호출 시점, Rule of Five와 Rule of Zero
- C++ 사용자 정의 리터럴: 리터럴 연산자 문법, cooked·raw 오버로드, 접미사 규칙
- C++ 소멸자와 RAII: 가상 소멸자, 규칙 0, 소멸자에서의 예외
- C++ 속성(Attributes): [[nodiscard]]·[[deprecated]]·[[likely]]·[[fallthrough]] 실전 사용법
- C++ 연산자 오버로딩: 멤버·비멤버 선택, 산술·비교·입출력 연산자 구현
- C++ 임시 객체: 생성·소멸 시점, const 참조 수명 연장 규칙, 댕글링 참조
- C++ 전방 선언: 헤더 의존성 줄이기, 불완전 타입의 제약, Pimpl 소멸자 위치
- C++ 전역 변수가 문제를 일으키는 5가지 경우와 대안: 초기화 순서, 스레드 안전성, 테스트
- C++ 전처리 지시자: 매크로 부작용, #if·#ifdef 조건부 컴파일, -E로 결과 확인
- C++ 캐스팅 4가지: static_cast·dynamic_cast·const_cast·reinterpret_cast 언제 쓰나
- C++ 캐시 교체 알고리즘: FIFO·LRU·LFU·Clock·MRU·OPT 구현과 비교
- C++ 타입 변환: 암시적 변환, static_cast·dynamic_cast·const_cast·reinterpret_cast, explicit
- C++ 파일 입출력: ifstream·ofstream 기초부터 에러 처리, 버퍼링, 원자적 쓰기까지
- C++ 함수 객체(펑터): 상태를 가진 호출 객체, STL 알고리즘 활용, 람다와의 차이
- C++ constexpr 함수: 컴파일 타임 평가 조건과 C++11·14·17 제약 변화
- C++ extern과 링키지: 전역 변수 공유, 내부·외부 연결, C 함수 연동
- C++ filesystem::path: 경로 결합·분해, absolute·canonical·relative 차이
- C++ inline의 진짜 의미: 인라인 확장이 아니라 ODR 예외, inline 변수와 constexpr
- C++ JSON 파싱: nlohmann/json vs RapidJSON, 커스텀 타입 직렬화, null·타입 에러 처리
- C++ namespace 심화: using 선언 vs 지시문, 익명 namespace, 인라인 namespace, ADL
- C++ nlohmann/json 실전: 파싱·커스텀 타입 직렬화·에러 처리와 자주 틀리는 동작
- C++ noexcept 지정자: 이동 생성자·swap·소멸자에 붙이는 이유와 위반 시 terminate
- C++ Rule of Five 직접 구현하기: copy-and-swap, 자기 대입, noexcept 이동 연산
- C++ std::async와 launch 정책: future, deferred 실행, 흔한 함정
- C++ std::bind와 placeholders: 부분 적용, 멤버 함수 바인딩, 람다로 바꿀 때
- C++ std::locale과 facet: 숫자·통화·날짜를 지역 형식으로 출력하기
- C++ std::ratio: 컴파일 타임 분수 연산과 chrono 단위 표현 원리
- C++ std::regex 실전: regex_match vs regex_search, 캡처 그룹, 토큰화와 탐욕적 매칭 함정
- C++ std::tuple: 여러 값 반환, std::tie와 구조적 바인딩, 구조체와 비교
- C++ thread_local: 스레드별 카운터·버퍼, 초기화 시점과 소멸 순서
- C++ unique_ptr vs shared_ptr: 소유권 모델과 비용 차이, 무엇을 기본으로 쓸까
- C++11 중괄호 초기화: narrowing 방지, Most Vexing Parse, vector<int>{10}과 (10)의 차이
- C++17 std::invoke와 std::apply: INVOKE 규칙과 튜플을 인자로 펼치는 원리
- C++20 삼원 비교 연산자 <=>: strong·weak·partial_ordering 고르는 기준과 = default
- C++20 std::ranges 알고리즘: projection으로 중복 줄이기와 concept 기반 에러
- C++20 std::span 심화: 정적·동적 extent, subspan, 읽기 전용 뷰
- std::optional로 '값 없음' 표현하기: value_or, C++23 and_then·transform, 에러 처리 패턴
- X-Macro로 중복 없애기: enum↔문자열 매핑, 에러 코드 표, 상태 머신, 커맨드 테이블
고급 (33편)
- 임베디드 C++ 최적화: 플래시 크기, RAM 정적 할당, 전력 소모, 실시간성(WCET)
- C++ 값 카테고리: lvalue, prvalue, xvalue를 구분하는 기준
- C++ 객체 풀 구현: RAII 반납 래퍼, 동적 확장, reset 누락과 스레드 안전
- C++ 람다 참조 캡처 심화 — 수명 의미론, 캡처 규칙, ASAN, 실무 안전 패턴
- C++ 람다 표현식 심화 | 클로저 타입·캡처·제네릭 연역·IIFE·실무 패턴
- C++ 성능 최적화 순서: 복사 제거, 할당 줄이기, 캐시 지역성, 컴파일러 옵션
- C++ 인라인 어셈블리: GCC 확장 asm 제약 문자·clobber, MSVC 차이, 인트린식이 나은 경우
- C++ 제약된 환경에서의 C++: Exception과 RTTI 없이 안전한 코드 짜기
- C++ 직렬화 방식 비교: nlohmann·simdjson·Glaze JSON, 바이너리, Protobuf, C++26 리플렉션
- C++ 커스텀 Allocator: 메모리 풀·스택·추적 할당자와 PMR
- C++ 타입 소거(Type Erasure): std::function 내부 원리와 Concept·Model 직접 구현
- C++ 태그 디스패칭: iterator_category로 오버로드 고르기와 if constexpr·Concepts 비교
- C++ 템플릿 메타프로그래밍 심화 — SFINAE·타입 특성·태그 디스패치
- C++ 템플릿 인자 추론 규칙: 값·참조·전달 참조, decay, CTAD
- C++ 함수형 프로그래밍 심화 — 고차 함수·모나드·Ranges
- C++ ADL(인자 종속 조회): swap 관용구가 동작하는 이유와 엉뚱한 함수가 호출될 때
- C++ const·constexpr 내부 동작 | 평가 시점·if constexpr
- C++ CRTP: 가상 함수 없이 정적 다형성 구현하기와 C++23 deducing this
- C++ Expression Templates: 벡터 연산의 임시 객체를 없애는 지연 평가 구현
- C++ GUI | Qt 프레임워크: 위젯부터 MOC·시그널/슬롯·이벤트 루프·Graphics View까지
- C++ inline namespace로 API 버전 관리하기: 기본 버전 전환과 ABI 불일치 검출
- C++ Mixin 패턴: 템플릿 상속으로 로깅·카운팅 기능 조합하기
- C++ Move 시맨틱스: 복사와 이동의 차이, rvalue 참조, std::move
- C++ SFINAE vs Concepts | 언제 마이그레이션해야 할까
- C++ Visitor 패턴: 더블 디스패치와 std::variant + std::visit 비교
- C++ vtable과 vptr: 가상 함수 호출이 동작하는 방식과 메모리·호출 비용
- C++14 초기화 캡처: move 캡처와 unique_ptr을 람다에 넘기는 패턴
- C++17 실행 정책 seq·par·par_unseq: 병렬 알고리즘과 데이터 레이스 함정
- C++17·20·23 주요 기능 정리: 구조화 바인딩부터 Concepts·Ranges·std::print까지
- C++20 range adaptor: views::filter·transform 파이프라인의 지연 평가와 댕글링 함정
- C++20 ranges의 개념 계층: range 요건, input·forward·random_access_range, CPO 설계
- C++20 std::views: filter·transform·take 지연 평가와 ranges::to로 구체화하기
- C++23 std::expected: 예외 없이 에러 전달하기와 and_then 체이닝