상수와 상수 표현식 : const vs constexpr
개요
C++에서 const
와 constexpr
는 모두 상수를 정의하는 데 사용되지만, 초기화 시점과 컴파일 타임 평가 여부에서 중요한 차이가 있습니다. const
는 런타임에 초기화될 수 있는 읽기 전용 변수를 선언하는 반면, constexpr
는 컴파일 타임에 값이 결정되는 진정한 의미의 상수를 선언하여 컴파일러 최적화와 타입 시스템에 더 많은 정보를 제공합니다.
C++ 버전별 주요 키워드 도입 시기
- C++98:
const
키워드를 사용하여 읽기 전용 변수를 선언했습니다. - C++11:
constexpr
키워드가 도입되어, 변수나 함수가 컴파일 타임에 평가될 수 있음을 명시적으로 나타낼 수 있게 되었습니다. - C++14:
constexpr
함수의 제약이 완화되어, 지역 변수 선언, 반복문, 조건문 등을 포함할 수 있게 되어 활용성이 크게 향상되었습니다.
내용 설명
const
const
로 선언된 변수는 초기화된 이후 값을 변경할 수 없는 읽기 전용(read-only) 속성을 가집니다. 하지만 초기화 자체는 런타임에 수행될 수 있습니다.
- 초기화: 런타임에 결정되는 값으로 초기화될 수 있습니다. (예: 함수 반환 값, 사용자 입력 등)
- 사용: 주로 실행 중에 변하지 않아야 할 값을 보호하는 목적으로 사용됩니다.
int get_value() { return 10; }
const int val1 = 10; // 컴파일 타임 상수
const int val2 = get_value(); // 런타임에 초기화되는 상수
constexpr
(Constant Expression)
constexpr
는 컴파일 타임 상수(compile-time constant)를 선언하는 데 사용됩니다. constexpr
로 선언된 변수나 함수의 결과는 반드시 컴파일 시점에 그 값을 결정할 수 있어야 합니다.
- 초기화: 반드시 컴파일 타임에 알 수 있는 값으로 초기화되어야 합니다.
- 사용: 컴파일 타임에 계산을 완료하여 프로그램의 런타임 성능을 향상시키거나, 템플릿 메타프로그래밍, 배열 크기 지정 등 컴파일 시점에 값이 필요한 곳에 사용됩니다.
constexpr
변수는 암시적으로const
속성을 가집니다.
예제 코드
#include <iostream>
#include <cstdint>
// C++14 이상에서는 내부 로직이 더 복잡해질 수 있습니다.
constexpr std::uint64_t faculty(const std::uint8_t n)
{
// C++11 constexpr 함수는 return 문 하나만 허용했지만,
// C++14부터는 지역 변수, 루프, 조건문 등을 사용할 수 있습니다.
auto result = std::uint64_t{1};
for (std::uint8_t i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
int main()
{
// 1. const 변수: 런타임에 초기화될 수 있음
std::cout << "런타임에 값을 입력하세요: ";
int input;
std::cin >> input;
const int runtime_const = input; // OK: 런타임 값으로 초기화
// 2. constexpr 변수: 컴파일 타임에 값이 결정되어야 함
constexpr auto compile_time_val = faculty(5); // OK: 컴파일 타임에 계산됨
// constexpr auto runtime_val = faculty(input); // ERROR: input은 컴파일 타임 상수가 아님
// 3. 컴파일 타임 상수 활용
int arr[compile_time_val]; // OK: 배열 크기는 컴파일 타임 상수가 필요함
// int arr2[runtime_const]; // ERROR: C-style 배열 크기는 컴파일 타임 상수가 필요함 (단, 일부 컴파일러 확장 기능으로 허용될 수 있음)
std::cout << "faculty(5) = " << compile_time_val << std::endl;
std::cout << "런타임 상수 값: " << runtime_const << std::endl;
std::cout << "배열 arr의 크기: " << sizeof(arr) / sizeof(int) << std::endl;
return 0;
}
실행 결과
런타임에 값을 입력하세요: 10
faculty(5) = 120
런타임 상수 값: 10
배열 arr의 크기: 120
활용팁
- 성능 최적화: 런타임에 수행될 계산을 컴파일 타임으로 옮겨 프로그램의 실행 속도를 높일 수 있습니다. 복잡한 수학 계산, 테이블 생성 등을
constexpr
함수로 구현하면 좋습니다. - 컴파일 타임 안정성: 배열의 크기, 템플릿 인자,
static_assert
등 컴파일 시점에 값이 확정되어야 하는 곳에constexpr
를 사용하면 코드의 안정성과 명확성이 향상됩니다. const
와constexpr
의 선택 기준:- 값이 컴파일 시점에 확정될 수 있다면 항상
constexpr
를 우선적으로 사용하세요. - 값이 런타임에 결정되지만, 한 번 초기화된 후 변경되지 않아야 한다면
const
를 사용하세요. (예: 설정 파일에서 읽어온 값)
- 값이 컴파일 시점에 확정될 수 있다면 항상
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : static local variables (98, 11) (0) | 2025.08.07 |
---|---|
Modern C++ : type conversions (11, 14, 17, 20) (3) | 2025.08.05 |
Modern C++ : designated initializers (20) (0) | 2025.08.04 |
Modern C++ : enum concepts (11, 20) (1) | 2025.08.03 |
Modern C++ : enum vs enum class (98, 11) (1) | 2025.08.02 |
Modern C++ 둘러보기 (4) | 2025.08.01 |