const 정확성: 읽기 전용 약속과 API 설계
12강. const 정확성: 읽기 전용 약속과 API 설계
이번 강의에서 해결할 문제
읽기만 하는 함수가 비-const 참조를 요구하면 호출자는 불필요하게 수정 가능성을 열어야 합니다. 반대로 캐시처럼 관찰상 값이 같다는 이유로 아무 멤버나 mutable로 만들면 스레드 안전성과 불변식이 흐려집니다.
학습 목표
먼저 알아야 할 핵심 개념
const는 타입의 어느 부분을 읽기 전용으로 보는지에 따라 의미가 달라집니다. const Task*는 포인터로 대상 값을 수정할 수 없지만 다른 주소를 가리킬 수 있습니다. Task* const는 포인터 값은 바꿀 수 없지만 대상 수정은 가능합니다. const 멤버 함수는 this가 const 대상처럼 취급됩니다.
왜 이 문제가 위험한가
const를 제거해 실제 const 객체를 수정하면 UB가 될 수 있습니다. 읽기 함수가 내부 상태를 임의로 바꾸면 같은 입력에서 결과가 달라지고 멀티스레드 읽기 안전성도 오해하게 됩니다. const는 보안 장치가 아니라 컴파일 가능한 사용 범위를 제한하는 계약입니다.
가장 작은 예제로 시작하기
#include <iostream>
#include <string>
#include <utility>
class Task {
public:
explicit Task(std::string name) : name_{std::move(name)} {}
const std::string& name() const noexcept { return name_; }
bool isCompleted() const noexcept { return completed_; }
void complete() noexcept { completed_ = true; }
private:
std::string name_;
bool completed_{};
};
void printTask(const Task& task) {
std::cout << task.name() << ':' << std::boolalpha
<< task.isCompleted() << '\n';
}
int main() {
Task task{"build"};
printTask(task);
task.complete();
printTask(task);
}
코드 한 줄씩 이해하기
name()과isCompleted()는 관찰 함수라 const 객체에서도 호출할 수 있습니다.name()은 내부 문자열을 읽기 전용 참조로 돌려 불필요한 복사를 피합니다.- 반환 참조는
Task보다 오래 보관하면 안 됩니다. complete()만 논리 상태를 수정하므로 비-const 멤버 함수입니다.printTask는 읽기만 하므로const Task&를 받습니다.
실행 결과와 메모리·동작 흐름
첫 출력은 build:false, 완료 후는 build:true입니다. 관찰 함수는 상태를 바꾸지 않고 명령 함수만 불변식을 변경합니다. 반환된 이름 참조는 각 호출 표현식 안에서 즉시 사용됩니다.
단계별 실습
흔한 실수와 해결 방법
언제 사용하고 언제 피할까
관찰 API와 읽기 전용 입력에는 const를 기본으로 사용합니다. 단순히 컴파일 오류를 우회하려고 const_cast를 사용하지 않습니다. 캐시는 외부 관찰 상태와 스레드 안전성을 검토한 제한적 경우에만 mutable을 고려합니다.
게임 개발 연결
상태 조회와 상태 변경을 분리하면 업데이트 순서와 테스트가 명확해집니다. const만으로 멀티스레드 안전이 보장되지는 않지만 잘못된 수정 경로를 줄입니다.
이해 점검 질문 3개
const Task*와Task* const는 무엇을 바꿀 수 없나요?- const 멤버 함수가 논리 상태를 바꾸지 않는 계약이 테스트에 어떤 도움을 주나요?
- const 참조 반환값을 소유 객체보다 오래 보관하면 왜 위험한가요?
핵심 요약
다음 강의 연결
13강. 값·참조·포인터 전달에서 const와 소유권 기준에 성능 판단을 더합니다.
const 정확성: 읽기 전용 약속과 API 설계 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.