C++ const Complete Guide
이 글의 핵심
const-correctness is a C++ convention that reduces bugs by compiler-enforcing values and APIs that should not change. This guide explains const variables, member functions, pointer declarations, and mutable combinations with examples.
const Variables
const expresses “immutable” and is recommended in code review. Used with mutable, you can have exceptionally modifiable members like cache and locks. Combined with function basics and smart pointers, you can create read-only interfaces.
const int x = 10;
// x = 20; // Error: const variable cannot be modified
const int y; // Error: const must be initialized at declaration
const Functions
class Point {
private:
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
// const member function (does not change object state)
int getX() const { return x; }
int getY() const { return y; }
// non-const member function
void setX(int newX) { x = newX; }
};
int main() {
const Point p(10, 20);
cout << p.getX() << endl; // OK
// p.setX(30); // Error: const object cannot call non-const function
}
const Pointers
const Pointer Patterns
| Declaration | Modify Pointer | Modify Value | Read As |
|---|---|---|---|
const int* ptr | ✅ | ❌ | “pointer to const int” |
int* const ptr | ❌ | ✅ | “const pointer to int” |
const int* const ptr | ❌ | ❌ | “const pointer to const int” |
int const* ptr | ✅ | ❌ | Same as const int* |
int x = 10;
int y = 20;
// 1. Value pointed to is const
const int* ptr1 = &x;
// *ptr1 = 20; // Error
ptr1 = &y; // OK
// 2. Pointer itself is const
int* const ptr2 = &x;
*ptr2 = 20; // OK
// ptr2 = &y; // Error
// 3. Both const
const int* const ptr3 = &x;
// *ptr3 = 20; // Error
// ptr3 = &y; // Error
Memorization tip: What’s to the right of const is const
const Pointer Visualization
graph TD
A[const int* ptr] --> B[ptr modifiable]
A --> C[*ptr not modifiable]
D[int* const ptr] --> E[ptr not modifiable]
D --> F[*ptr modifiable]
G[const int* const ptr] --> H[ptr not modifiable]
G --> I[*ptr not modifiable]
const Reference
void process(const vector<int>& v) {
// Only read v (no copy)
for (int x : v) {
cout << x << " ";
}
// v.push_back(10); // Error
}
int main() {
vector<int> data = {1, 2, 3};
process(data); // Pass without copy
}
mutable
mutable Usage Scenarios
| Scenario | Example | Reason |
|---|---|---|
| Caching | Store calculation result | Logically const, physically changed |
| Statistics | Count access count | Observation-only action |
| Synchronization | mutable mutex | Lock is not logical state |
| Lazy initialization | Initialize on first access | Read action but internal change |
class Cache {
private:
mutable int accessCount; // Modifiable even in const function
int value;
public:
Cache(int v) : value(v), accessCount(0) {}
int getValue() const {
accessCount++; // OK: mutable
return value;
}
int getAccessCount() const {
return accessCount;
}
};
int main() {
const Cache cache(42);
cout << cache.getValue() << endl; // accessCount incremented
cout << cache.getAccessCount() << endl; // 1
}
Practical Examples
Example 1: const Correctness
class String {
private:
char* data;
size_t length;
public:
String(const char* str) {
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
}
~String() {
delete[] data;
}
// const version
const char* c_str() const {
return data;
}
// non-const version
char* c_str() {
return data;
}
size_t size() const {
return length;
}
};
void print(const String& s) {
cout << s.c_str() << endl; // Calls const version
}
Example 2: const and Iterators
#include <vector>
using namespace std;
void process(const vector<int>& v) {
// Use const_iterator
for (vector<int>::const_iterator it = v.begin();
it != v.end(); ++it) {
cout << *it << " ";
// *it = 10; // Error
}
// Or use auto
for (auto it = v.cbegin(); it != v.cend(); ++it) {
cout << *it << " ";
}
}
Example 3: const and Thread Safety
#include <mutex>
class ThreadSafeCounter {
private:
mutable mutex mtx; // Can lock even in const function
int count;
public:
ThreadSafeCounter() : count(0) {}
void increment() {
lock_guard<mutex> lock(mtx);
count++;
}
int getCount() const {
lock_guard<mutex> lock(mtx); // OK: mutable
return count;
}
};
Summary
Key Points
- const variables: Cannot be modified after initialization
- const functions: Do not modify object state
- const pointers: Four patterns (pointer/value const)
- const reference: Pass without copy
- mutable: Modifiable in const functions
Best Practices
- ✅ Use const for read-only parameters
- ✅ Mark member functions const when possible
- ✅ Use const reference for large objects
- ✅ Use mutable for cache/statistics
- ❌ Don’t cast away const
- ❌ Don’t abuse mutable
Related Articles
Master const correctness for safer C++ code! 🚀
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. const-correctness is a C++ convention that reduces bugs by compiler-enforcing values and APIs that should not change. Th… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ Complete Guide to const | Practical Use of ‘Const Correctness’
- C++ typedef vs using | ‘타입 별칭’ 가이드
- C++ Custom Deleters | ‘커스텀 삭제자’ 가이드
이 글에서 다루는 키워드 (관련 검색어)
C++, const, const-correctness, constant, code-quality 등으로 검색하시면 이 글이 도움이 됩니다.