-
const 키워드 맥락에 따라 구분하기Programming🧑💻/Cpp 2025. 4. 6. 21:06
const 키워드는 C++에서 매우 중요한 개념으로, 코드의 안정성과 가독성을 높이는 데 큰 역할을 합니다. 하지만 다양한 상황에서 활용되기 때문에 언어에 익숙하지 않은 경우, 맥락에 따른 의미를 파악하기 어려울 수 있습다. 이번 글에서는 다양한 곳에서 cosnt가 어떻게 활용되는지 살펴보도록 하겠습니다.
1. 상수 변수 선언
가장 기본적인 const 사용법은 변수를 상수로 선언하는 것입니다.
const int MAX_USERS = 100; const double PI = 3.14159265359;이렇게 선언된 변수는 초기화 후 값을 변경할 수 없습니다.
2. 포인터와 const
const와 포인터를 함께 사용할 때는 두 가지 경우가 있습니다. const 키워드는 자신의 왼쪽에 있는 것을 상수로 만듭니다. 하지만 왼쪽에 아무것도 없다면, 오른쪽에 있는 것을 상수로 만듭니다.
2.1 상수 데이터를 가리키는 포인터 (pointer to constant) - * 를 기준으로 왼쪽에 있는 경우
const int* ptr; int const* ptr; // 위와 동일한 의미이 경우, 포인터가 가리키는 데이터를 변경할 수 없지만, 포인터 자체는 다른 주소를 가리키도록 변경할 수 있습니다.
const int x = 10; const int y = 20; const int* ptr = &x; // x를 가리킴 ptr = &y; // 가능: 포인터가 y를 가리키도록 변경 // *ptr = 30; // 오류: 가리키는 값을 변경할 수 없음2.2 상수 포인터 (constant pointer) - * 를 기준으로 오른쪽에 있는 경우
int* const ptr = &someInt;이 경우, 포인터가 가리키는 주소는 변경할 수 없지만, 가리키는 데이터의 값은 변경할 수 있습니다.
int x = 10; int y = 20; int* const ptr = &x; // x를 가리킴 // ptr = &y; // 오류: 포인터가 다른 주소를 가리키도록 변경할 수 없음 *ptr = 30; // 가능: x의 값이 30으로 변경됨2.3 상수 데이터를 가리키는 상수 포인터 (constant pointer to constant)
const int* const ptr = &someInt;이 경우, 포인터가 가리키는 주소도 변경할 수 없고, 가리키는 데이터의 값도 변경할 수 없습니다.
3. 함수 매개변수에서의 const
3.1 값으로 전달되는 매개변수
void function(const int value) { // value 값을 변경할 수 없음 }이 경우 함수 내에서 매개변수 값을 변경하지 않겠다고 명시하는 의미가 있습니다만, 값이 복사되므로 실질적인 제약은 크지 않습니다.
3.2 참조로 전달되는 매개변수
void function(const std::string& text) { // text를 변경할 수 없음 std::cout << text.length() << std::endl; // 읽기는 가능 }이 방식은 특히 중요합니다. 큰 객체를 함수에 전달할 때 복사 비용을 줄이면서도 원본 데이터가 변경되지 않도록 보호합니다.
4. 함수 반환 타입에서의 const
4.1 기본 데이터 타입 반환
기본 데이터 타입(int, double 등)의 경우, 반환 값에 const를 붙이는 것은 실질적인 효과가 없습니다.
const int getValue() { return 42; }이 경우, 반환된 값은 임시 값이므로 어차피 수정할 수 없습니다. 따라서 const가 있든 없든 실제 동작에 차이가 없습니다. 이런 이유로 기본 타입에는 보통 const를 반환 타입에 사용하지 않습니다.
4.2 객체나 참조 반환시 const
객체나 참조를 반환할 때 const를 사용하면 중요한 의미가 있습니다.
class DataStore { public: // 상수 객체 반환 - 수정 불가능 const std::vector<int> getData() const { return data; } // 상수 참조 반환 - 내부 데이터에 대한 읽기 전용 접근 const std::vector<int>& getDataRef() const { return data; } private: std::vector<int> data; };이런 경우, 반환된 객체나 참조를 통해 원본 데이터를 수정할 수 없게 됩니다.
4. 3 포인터 반환시 const
포인터 반환에서는 const의 위치에 따라 의미가 달라집니다.
// 포인터가 가리키는 데이터가 상수 (데이터 수정 불가) const int* getDataPointer() { static int value = 10; return &value; } // 상수 포인터 반환 (별로 의미 없음, 임시값이므로) int* const getConstPointer() { static int value = 10; return &value; } // 상수 데이터를 가리키는 상수 포인터 const int* const getReallyConstPointer() { static int value = 10; return &value; }여기서 첫 번째와 세 번째 예제가 가장 일반적입니다. 이는 함수가 반환하는 포인터가 가리키는 데이터를 수정할 수 없게 합니다.
5. 클래스 멤버 함수에서의 const
5.1 상수 멤버 함수
class MyClass { public: int getValue() const { // 클래스의 멤버 변수를 변경할 수 없음 return m_value; } private: int m_value; };상수 멤버 함수는 객체의 상태를 변경하지 않는다는 것을 보장합니다. 이는 특히 다음과 같은 경우에 중요합니다.
const MyClass obj; obj.getValue(); // 상수 객체는 상수 멤버 함수만 호출할 수 있음5.2 멤버 변수의 상수 선언
class Config { private: const int MAX_CONNECTIONS = 100; // 초기화 후 변경 불가능 };6. 템플릿과 함께 사용
template<const int SIZE> class Buffer { char data[SIZE]; }; Buffer<1024> buffer; // 컴파일 타임에 크기가 결정됨7. constexpr과의 차이점
C++11부터 도입된 constexpr은 컴파일 시간에 평가될 수 있는 표현식을 나타냅니다.
constexpr int factorial(int n) { return (n <= 1) ? 1 : (n * factorial(n - 1)); } constexpr int result = factorial(5); // 컴파일 시간에 계산됨const가 값이 변경되지 않음을 나타낸다면, constexpr은 컴파일 시간에 평가될 수 있음( 컴파일 시간에 계산이 이미 됨)을 나타냅니다.

'Programming🧑💻 > Cpp' 카테고리의 다른 글
가상 함수와 함수 호출 방식( 정적 디스패칭, 동적 디스패칭 ) (0) 2025.04.07 inline 키워드 알아보기 (0) 2025.04.05 헤더 전용 라이브러리는 뭐고 언제 쓸까? (0) 2025.04.04 상태기계와 코루틴 프레임 (0) 2025.02.14 서브 루틴과 코루틴 (0) 2025.02.13