7장 : 포인터와 참조
const 포인터와 포인터 상수
포인터를 실제 코드에서 안전하게 사용하려면 const가 포인터에 붙는 위치에 따라 의미가 어떻게 달라지는지 정확히 이해해야 합니다.
많은 초급자들이 const int*, int* const, const int* const를 헷갈리며, 이 혼동이 버그로 이어지는 경우가 많습니다.
이 장에서는 세 가지 선언을 명확히 구분하고, 함수 매개변수 설계에서 어떤 형태를 선택해야 하는지 실전 기준으로 정리하겠습니다.
const가 가리키는 대상에 붙는 경우 (const int*)
const int* ptr는 포인터가 가리키는 값을 수정할 수 없다는 의미입니다.
- 포인터 자체(
ptr)는 다른 주소를 가리키도록 변경할 수 있습니다. - 하지만
*ptr을 통해 값을 바꾸는 것은 금지됩니다.
#include <iostream>
int main() {
int a = 10;
int b = 20;
const int* ptr = &a; // int const* ptr 와 동일
// *ptr = 30; // 컴파일 오류: 가리키는 값 수정 불가
ptr = &b; // 가능: 포인터가 다른 대상을 가리키는 것은 허용
std::cout << "*ptr = " << *ptr << "\n"; // 20
}포인터 자체가 상수인 경우 (int* const)
int* const ptr는 포인터 자체가 상수라는 뜻입니다.
ptr이 한 번 가리킨 주소는 바꿀 수 없습니다.- 대신 가리키는 값(
*ptr)은 수정할 수 있습니다.
#include <iostream>
int main() {
int a = 10;
int b = 20;
int* const ptr = &a;
*ptr = 30; // 가능: 대상 값 수정 가능
// ptr = &b; // 컴파일 오류: 포인터 자체는 변경 불가
std::cout << "a = " << a << "\n"; // 30
}둘 다 상수인 경우 (const int* const)
const int* const ptr는 포인터 자체도 상수, 가리키는 값도 상수입니다.
ptr재지정 불가*ptr수정 불가
#include <iostream>
int main() {
int value = 42;
const int* const ptr = &value;
// *ptr = 100; // 오류
// ptr = nullptr; // 오류
std::cout << *ptr << "\n";
}읽는 요령: 오른쪽에서 왼쪽으로
복잡한 선언은 변수 이름 기준으로 오른쪽에서 왼쪽으로 읽으면 해석이 쉬워집니다.
const int* p->p는 포인터, 가리키는int는 constint* const p->p는 const 포인터const int* const p-> const 포인터가 const int를 가리킴
함수 매개변수 설계에서의 선택 기준
포인터를 매개변수로 받을 때는 “함수가 무엇을 바꿀 수 있어야 하는가?”를 기준으로 결정합니다.
데이터를 읽기만 할 때
const T* 또는 const T&를 사용합니다.
double getLength(const Vector2* v);
double getLength(const Vector2& v);데이터를 수정해야 할 때
T* 또는 T&를 사용합니다.
void normalize(Vector2* v);
void normalize(Vector2& v);포인터 자체 재지정까지 막고 싶을 때
함수 내부 구현 관점에서 T* const를 사용할 수 있습니다.
void updateValue(int* const p) {
// p = nullptr; // 금지
*p = 99; // 허용
}실무에서는 API 사용자 입장에서 명확한 의도를 전달하기 위해 읽기 전용은 const, 수정 가능은 non-const를 엄격히 구분하는 것이 중요합니다.
포인터와 참조 중 무엇을 쓸까?
둘 다 원본 객체를 다룰 수 있지만, 용도가 다릅니다.
- 참조(
T&,const T&): 반드시 유효한 객체가 있어야 하며, null 개념이 없습니다. - 포인터(
T*,const T*): null(nullptr)을 표현할 수 있어 “없음” 상태를 전달하기 쉽습니다.
즉, “항상 대상이 존재한다”면 참조가 더 단순하고, “대상이 없을 수도 있다”면 포인터가 더 적절합니다.
포인터/참조 선택 기준 정리
const int*: 대상 값 수정 금지int* const: 포인터 재지정 금지const int* const: 둘 다 금지- 함수 설계에서는
const를 통해 읽기/수정 의도를 명확히 드러내는 것이 핵심입니다.