참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계
4강. 참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계
이번 강의에서 해결할 문제
모든 인자를 포인터로 받으면 호출자는 null 가능성과 소유권을 추측해야 합니다. 모든 인자를 const T&로 받으면 작은 값도 불필요하게 간접 접근하고 수정 의도도 숨습니다. 전달 방식은 빠르다는 소문이 아니라 API의 의미를 표현해야 합니다.
학습 목표
먼저 알아야 할 핵심 개념
참조는 일반적으로 이미 존재하는 객체의 별칭으로 사용합니다. 정상적인 참조는 null을 표현하지 않고 다른 객체로 재지정하지 않습니다. 포인터는 주소 값이므로 nullptr를 가질 수 있고 다른 주소를 다시 저장할 수 있습니다. 둘 다 비소유로 사용할 수 있으므로 대상 수명은 별도 계약입니다.
| 의도 | 추천 형태 | 호출자가 읽는 계약 |
|---|---|---|
| 작은 값 입력 | int amount | 독립 값, 수정 영향 없음 |
| 필수 읽기 전용 큰 값 | const Task& task | 반드시 존재, 복사 없음 |
| 필수 수정 대상 | Task& task | 반드시 존재, 원본 수정 |
| 선택적 비소유 대상 | Task* task | null 가능, 소유하지 않음 |
| 단일 소유권 이전 | std::unique_ptr<Task> | 호출 대상이 소유권을 넘김 |
왜 이 문제가 위험한가
선택적 포인터를 검사하지 않으면 null 역참조가 되고, 참조나 포인터를 장기 저장하면 호출자가 먼저 파괴할 수 있습니다. const T&를 멤버로 무심코 저장하는 것도 같은 댕글링 위험이 있습니다. 전달 문법만 맞아도 수명 계약이 틀리면 안전하지 않습니다.
가장 작은 예제로 시작하기
#include <algorithm>
#include <iostream>
#include <string>
struct Task {
std::string name;
int priority{};
};
void raisePriority(Task& task, int amount) {
task.priority = std::max(0, task.priority + amount);
}
void printTask(const Task& task) {
std::cout << task.name << ':' << task.priority << '\n';
}
void printSelected(const Task* task) {
if (task == nullptr) {
std::cout << "none\n";
return;
}
printTask(*task);
}
int main() {
Task build{"build", 2};
raisePriority(build, 1);
printTask(build);
printSelected(nullptr);
}
코드 한 줄씩 이해하기
raisePriority의Task&는 원본 수정이 필수임을 표현합니다.amount는 작은 독립 값이라 값 전달이 단순합니다.printTask는 필수 읽기 전용 객체를const Task&로 받습니다.printSelected는 선택 결과가 없을 수 있어const Task*를 받습니다.- 어느 raw pointer도 파괴 책임을 갖지 않습니다.
실행 결과와 메모리·동작 흐름
build.priority는 2에서 3으로 바뀌고 첫 줄에 build:3이 출력됩니다. 두 번째 호출은 대상이 없어 none을 출력합니다. 모든 참조와 포인터는 main의 build 수명 안에서만 사용되고 저장되지 않습니다.
단계별 실습
흔한 실수와 해결 방법
언제 사용하고 언제 피할까
필수 입력은 값 또는 참조, 선택 입력은 포인터, 소유권 이전은 스마트 포인터나 값으로 표현합니다. 성능은 프로파일링으로 확인하되 먼저 호출자가 오해할 수 없는 계약을 만듭니다.
게임 개발 연결
필수 설정, 수정 대상 상태, 선택된 대상은 서로 다른 API 계약입니다. 엔진과 무관하게 null 가능성과 수명 책임이 시그니처에 보여야 합니다.
이해 점검 질문 3개
- 참조와 포인터가 null 표현과 재지정에서 어떻게 다른가요?
const T&를 클래스 멤버로 저장할 때 어떤 수명 문제가 생길 수 있나요?- 소유권 이전을 raw pointer보다
unique_ptr값으로 표현하면 무엇이 명확해지나요?
핵심 요약
다음 강의 연결
5강. 동적 할당의 문제에서 raw pointer가 소유권까지 맡을 때 생기는 누수와 이중 해제를 분석합니다.
참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.