코드 읽기 좋은 설계: 값, 참조, 포인터를 구분하는 기초 기준
19강. 코드 읽기 좋은 설계: 값, 참조, 포인터를 구분하는 기초 기준
이번 강의에서 해결할 문제
모든 함수 인자를 포인터로 받으면 null 여부와 소유권을 매번 추측해야 합니다. 모든 값을 복사하면 큰 객체 비용과 수정 결과가 사라질 수 있습니다. 타입 선택은 성능 요령보다 함수 계약을 읽게 하는 도구입니다.
학습 목표
- 값 전달, 참조 전달, 포인터 전달의 기본 의미를 구분합니다.
- 필수 입력과 선택 입력을 시그니처에 표현합니다.
- 작은 값 복사와 큰 객체 참조를 상황에 맞게 선택합니다.
먼저 알아야 할 핵심 개념
값 인자는 독립 복사본이며 함수가 바꿔도 호출자 값은 그대로입니다. 참조는 반드시 존재하는 객체의 별칭으로 사용하며 const T&는 복사 없이 읽습니다. 포인터는 nullptr로 대상 없음이 가능하고 다른 대상을 가리킬 수 있습니다. raw pointer 인자는 기본적으로 소유권 이전이 아니라 관찰로 문서화합니다.
가장 작은 실행 가능한 예제
#include <iostream>
#include <string>
struct Player {
std::string name;
int health;
};
int doubled(const int value) {
return value * 2;
}
void heal(Player& player, const int amount) {
player.health += amount;
}
void inspect(const Player* player) {
std::cout << (player == nullptr ? "no player" : player->name) << '\n';
}
int main() {
Player hero{"Mina", 70};
heal(hero, doubled(10));
inspect(&hero);
inspect(nullptr);
std::cout << hero.health << '\n';
}
핵심 코드 줄별 설명
- 작은 정수는 값으로 받아 독립 계산합니다.
heal은 반드시 존재하는 플레이어 원본을 수정해Player&를 사용합니다.- 검사 대상은 없을 수 있어 포인터로 받습니다.
- 포인터 함수는 역참조 전에 null을 처리합니다.
- 어느 함수도 플레이어 소유권을 가져가지 않습니다.
실행 결과와 값 변화
Mina
no player
90
heal을 Player player 값 인자로 바꾸면 함수 내부 복사본만 90이 되고 마지막 출력은 70으로 남습니다.
단계별 실습
실습 목표
아이템 조회·수정 함수에 의도가 맞는 인자 타입을 선택합니다.
시작 전 상태와 실행 방법
이름과 수량이 있는 Item 구조체를 준비합니다.
1단계: 최소 코드 작성
작은 할인율은 값으로, 아이템 읽기는 const Item&로 받는 출력 함수를 만듭니다.
2단계: 값 또는 조건을 바꿔 결과 비교
수량 변경 함수를 값과 참조로 각각 작성해 원본 차이를 확인합니다.
3단계: 작은 기능 확장
선택된 아이템이 없을 수 있는 출력 함수는 const Item*로 받고 null을 처리합니다.
4단계: 스스로 해결하기
문자열 이름을 값, const string&, string_view 중 무엇으로 받을지 함수가 보관하는지 여부를 기준으로 선택하세요.
막혔을 때
const 참조에서 멤버를 수정할 수 없다는 오류는 읽기 전용 계약이 작동한 결과입니다. 수정이 요구사항인지 다시 확인한 뒤에만 비const 참조로 바꿉니다.
흔한 실수와 해결 방법
- 포인터가 빠르다는 이유만으로 사용: null 가능성과 수명 추적 비용이 생깁니다.
- 수정 결과가 필요한데 값 전달: 원본을 수정해야 한다면 참조 또는 반환값을 사용합니다.
- raw pointer로 소유권 전달: 소유권 이동은
unique_ptr등 명시적 타입으로 표현합니다.
게임 개발 연결
대미지 값은 값, 반드시 존재하는 캐릭터 수정은 참조, 선택 타깃 관찰은 포인터처럼 계약을 나눌 수 있습니다. 엔진 API의 객체 포인터는 GC·스레드·유효성 규칙이 추가되므로 일반 C++ 포인터 판단에 엔진 계약을 함께 적용합니다.
이해 점검 질문 3개
- 값 인자를 수정해도 호출자 객체가 바뀌지 않는 이유는 무엇인가요?
- 필수로 존재하는 수정 대상에 참조가 어울리는 이유는 무엇인가요?
- raw pointer 인자와 unique_ptr 인자가 소유권 측면에서 어떻게 다른가요?
핵심 요약
인자 타입은 복사·필수 대상·선택 대상·소유권을 표현합니다. 미세 성능보다 호출자가 계약을 바로 읽고 잘못된 상태를 만들기 어렵게 하는 선택을 우선합니다.
다음 강의 연결
20강. 인벤토리와 퀘스트 도구에서 지금까지 배운 값 타입, 컨테이너, optional, 알고리즘과 단일 소유권을 하나의 프로그램으로 통합합니다.
코드 읽기 좋은 설계: 값, 참조, 포인터를 구분하는 기초 기준 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.