const와 constexpr

김민서·2025년 11월 24일

C/C++

목록 보기
6/6

들어가며

개인 프로젝트를 하면서 constexpr을 알게 되었다. constconstexpr 차이는 이해했다. 하지만 const만으로도 충분해 보이는데, 왜 굳이 constexpr가 필요한 건지 궁금했다. 정보를 찾은 결과를 이 글에 남겨보고자 한다.


const

값을 변경할 수 없다는 약속을 컴파일러에게 하는 키워드다.
한 번 초기화된 후에는 그 값을 바꿀 수 없다.

const int MAX_USERS = 100;
MAX_USERS = 200;  // 컴파일 에러!

특징

  • 초기화 값은 컴파일 타임에 알 수도 있고, 런타임에 알 수도 있다.
int A;
std::cin >> A;

const int B = A;  // 가능
// 상수 B는 런타임에 결정되지만, 이후 변경은 불가하다.
// 컴파일 타임에 값을 몰라도 되지만, 한 번 정해지면 변경할 수 없다.
  • 참조와 포인터와 함께 사용될 때 더욱 강력해진다.
const int* ptr1;       	// 가리키는 값을 바꿀 수 없음
int* const ptr2;       	// 포인터 자체를 바꿀 수 없음
const int* const ptr3; 	// 둘 다 바꿀 수 없음
  • 클래스의 멤버 함수에 const를 붙이면, 그 함수는 객체의 상태를 변경하지 않겠다고 약속하는 것이다.
class User {
private:
    std::string name;
    int age;

public:
    // 멤버 변수를 수정하지 않음
    std::string getName() const {
        return name;
        // age = 30;  // 에러 발생
    }
    
    void setAge(int newAge) {
        age = newAge; // 가능
    }
};

한계

  • 멤버 변수를 mutable로 선언하면 const 멤버 함수에서도 수정할 수 있다.
  • const_castconst를 강제로 제거할 수 있다.

constexpr

constexpr은 constant expression의 약자로,
const와 달리 컴파일 타임에 반드시 결정된다는 보장을 컴파일러에게 하는 키워드다.
C++11에서 처음 등장했고 버전 업을 거치면서 대부분의 제약이 풀렸다.

constexpr int func(int n) {
    return n * n;
}

constexpr int A = 1;  		// 컴파일 타임에 1로 초기화된다.
constexpr int B = func(2);  // 컴파일 타임에 4로 계산된다.
constexpr int C = func(B);  // 컴파일 타임에 16로 계산된다.

const와 결정적 차이는 아래와 같다:

int func() { 
    int value;
    std::cin >> value;
    return value;
}

const int a = func();      // 가능 -> 런타임에 결정되기 때문
constexpr int b = func();  // 에러 발생

사용 이유

  • 컴파일 타임 계산으로 복잡한 계산도 컴파일 타임에 끝낼 수 있도록 성능이 향상된다.
  • C++에서 배열 크기나 템플릿 인자는 컴파일 타임 상수여야 한다.
  • 잘못된 계산을 실행 전에 잡을 수 있다.
  • 컴파일러가 더 많은 검증을 수행할 수 있다.
// 1. 성능 향상
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(10);  // 실행 시 계산 비용 0

// 2. 배열 크기
constexpr int SIZE = 100;
int buffer[SIZE];  // OK

const int size = getSize();
int arr[size];  // 대부분 에러

// 3. 컴파일 타임 검증
constexpr int divide(int a, int b) {
    return b == 0 ? throw "error" : a / b;
}
constexpr int x = divide(10, 0);  // 컴파일 에러 발생

언제 const를 쓰고, constexpr을 써야할까?

const를 사용하는 경우

  • 사용자 입력, 파일에서 읽은 설정값, 런타임에 알 수도 있는 값일 때 사용한다.
  • 함수에 전달된 인자를 수정하지 않겠다는 의도를 표현할 때는 const를 사용한다.
  • 객체의 상태를 변경하지 않는 멤버 함수는 const로 선언한다.

constexpr을 사용하는 경우

  • C++ 배열의 크기는 컴파일 타임 상수여야 한다.
  • 템플릿 매개변수는 반드시 컴파일 타임에 결정되어야 한다.
  • 복잡한 계산을 미리 해두고 싶을 때 사용한다.
  • switch문의 case 레이블, static_assert 등에서 사용한다.
상황constconstexpr
사용자 입력값OX
배열 크기O
템플릿 인자XO
함수 파라미터OX
컴파일 타임 계산O

정리

const는 변경 불가의 약속이고, constexpr는 컴파일 타임 계산의 보장이다.
const는 런타임 값도 받을 수 있지만, constexpr는 오직 컴파일 타임에만 결정된다.

profile
시스템 개발 공부 중

0개의 댓글