본문으로 건너뛰기 C++ const Complete Guide

C++ const Complete Guide

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

DeclarationModify PointerModify ValueRead 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* ptrSame 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

ScenarioExampleReason
CachingStore calculation resultLogically const, physically changed
StatisticsCount access countObservation-only action
Synchronizationmutable mutexLock is not logical state
Lazy initializationInitialize on first accessRead 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

  1. const variables: Cannot be modified after initialization
  2. const functions: Do not modify object state
  3. const pointers: Four patterns (pointer/value const)
  4. const reference: Pass without copy
  5. 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

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++, const, const-correctness, constant, code-quality 등으로 검색하시면 이 글이 도움이 됩니다.