프로그래밍 언어/C++

C++ 최신 문법 총정리: C++11부터 C++23까지

해달이랑 2025. 4. 23. 01:42

 

 

C++11/14의 주요 기능

auto 키워드

auto 키워드는 컴파일러가 초기화 표현식으로부터 변수의 타입을 자동으로 추론할 수 있게 해준다.

auto x = "Chris"; // 올바름
auto x; // 에러 - 반드시 초기화 필요

// 포인터와 참조 사용
auto myCatPtr = myCat; // 포인터
auto& myCatRef = myCat; // 참조
const auto& value = getValue(); // const 참조

 

auto는 복잡한 타입을 간단하게 표현할 수 있어 특히 반복자나 템플릿 매개변수에 유용하다.

 

그러나 가독성을 위해 다음과 같이 주의해야 될 점이 있다.

  • auto보다 실제 자료형 사용을 권장
  • 템플릿 매개변수와 반복자에는 auto 사용
  • auto보다 auto*를 사용 (포인터일 경우)
  • auto&보다 const auto&를 사용 (참조일 경우)

nullptr

기존의 NULL 대신 도입된 nullptr은 포인터 타입에 특화된 null 값

Class* myClass = new Class("COMP3200");
const Student* student = myClass->GetStudent("Coco");
if (student != nullptr) {
    std::cout << student->GetID() << ":" << student->GetName() << std::endl;
}

 

nullptr은 정수 타입과의 모호함을 제거하여 함수 오버로딩 시 발생할 수 있는 문제를 해결


고정폭 정수형

크기가 명확한 정수 타입을 제공

int8_t / uint8_t    // 1바이트
int16_t / uint16_t  // 2바이트
int32_t / uint32_t  // 4바이트
int64_t / uint64_t  // 8바이트

범위 기반 for 문

배열이나 컨테이너를 순회할 때 더 간결한 문법을 제공

string companies[] = {"Apple", "Tesla", "Google", "Nvidia"};

// 기존 방식
for (int i = 0; i < sizeof(companies) / sizeof(string); i++) {
    cout << companies[i] << "\n";
}

// 범위 기반 for 문
for (string company : companies) {
    cout << company << "\n";
}

람다 표현식

익명 함수를 생성할 수 있는 람다 표현식을 도입

auto sum = [](int a, int b) { return a + b; };
std::cout << sum(3, 4); // 출력: 7

// 캡처 사용
int multiplier = 5;
auto multiply = [multiplier](int value) { return value * multiplier; };
std::cout << multiply(10); // 출력: 50

 

람다는 코드의 간결성과 가독성을 높이며, 알고리즘 함수에 콜백으로 전달하기에 편리


enum class

기존 enum의 문제점을 해결한 강력한 열거형

enum class Color : uint8_t {
    Black,
    White,
    Red,
    // Final = 0x100  // 경고! uint8_t 범위 초과
};

Color c = Color::Black; // 반드시 스코프 지정 필요

 

enum class는 형 안전성을 제공하고, 이름 충돌 문제를 해결


STL 확장

정렬되지 않은 컨테이너와 같은 새로운 STL 컨테이너가 추가

// unordered_map: 해시 테이블 기반 맵
std::unordered_map<std::string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;

// array: 고정 크기 배열의 STL 래퍼
std::array<int, 5> numbers = {1, 2, 3, 4, 5};

 

unordered_map은 탐색 시 O(1)의 성능을 제공하여 자주 조회가 필요한 경우 유용


 

C++17의 주요 기능

if-init 문

조건문 내부에서 변수 초기화

if (auto it = map.find(key); it != map.end()) {
    // it은 if 블록 내에서만 유효
    std::cout << it->second << std::endl;
} else {
    // it은 여기서도 유효
    std::cout << "Key not found" << std::endl;
}

C++20의 주요 기능

우주선 연산자(Spaceship Operator)

비교 연산을 단순화하는 새로운 연산자 <=>가 도입

#include <compare>

struct MyType {
    int value;
    auto operator<=>(const MyType& other) const = default;
};

int main() {
    MyType a{5};
    MyType b{10};
    
    auto result = a <=> b;
    if (result < 0)
        std::cout << "a is less than b\n";
    else if (result == 0)
        std::cout << "a is equal to b\n";
    else
        std::cout << "a is greater than b\n";
    
    return 0;
}

 

여러 비교 연산자(<, <=, >, >=, ==, !=)를 한 번에 정의할 수 있어 코드가 크게 간소화


컨셉(Concepts)

템플릿 매개변수에 제약 조건을 지정

template<typename T>
concept Numeric = std::is_arithmetic_v<T>;

template<Numeric T>
T add(T a, T b) {
    return a + b;
}

// 사용
auto result1 = add(5, 3);     // 정상
// auto result2 = add("a", "b"); // 컴파일 오류

 

템플릿 오류 메시지를 개선하고, 제약 조건을 명확하게 표현


코루틴(Coroutines)

함수 실행을 중간에 중단했다가 나중에 이어서 실행할 수 있는 코루틴

#include <coroutine>
#include <iostream>

struct Generator {
    struct promise_type {
        int value;
        
        Generator get_return_object() { return Generator{this}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always yield_value(int v) {
            value = v;
            return {};
        }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
    
    // 코루틴 구현 생략...
};

Generator range(int start, int end) {
    for (int i = start; i < end; i++) {
        co_yield i;
    }
}

 

코루틴은 비동기 프로그래밍, 이터레이터, 생성기 등 다양한 패턴을 구현하는 데 유용


모듈(Modules)

헤더 파일 대신 모듈을 사용하여 코드를 구성

// math.cppm
export module math;

export int add(int a, int b) {
    return a + b;
}

// main.cpp
import math;

int main() {
    int result = add(5, 3);
    return 0;
}

 

모듈은 컴파일 속도를 향상시키고, 헤더 파일의 여러 문제점을 해결


C++23의 주요 기능

std::print와 std::println

출력을 위한 새로운 함수

#include <print>

int main() {
    int age = 30;
    std::string name = "Alice";
    
    std::print("{}의 나이는 {}세입니다.\n", name, age);
    std::println("{}의 나이는 {}세입니다.", name, age); // 자동 개행
    
    return 0;
}

 

기존의 std::cout이나 printf보다 타입 안전성이 높고, 간결한 문법을 제공

 

- 숫자 형식 지정 예시

int number = 255;
std::print("10진수: {}, 16진수: {:#x}\n", number, number);
// 출력: 10진수: 255, 16진수: 0xff

 

std::format과 유사한 형식 지정자를 사용하여 다양한 출력 형식을 지원


연역 this 포인터

멤버 함수의 this 포인터 타입을 명시적으로 지정

struct S {
    void f(this S& self) {
        // 'this'가 아닌 'self'로 접근
    }
    
    template<typename Self>
    void g(this Self&& self) {
        // 보편 참조(universal reference)로 this 사용
    }
};