본문으로 건너뛰기
모던 C++ 심화LESSON 04

참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계

난이도중급 → 심화
예상 시간70분
선수지식이전 강의

4강. 참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계

이번 강의에서 해결할 문제​

모든 인자를 포인터로 받으면 호출자는 null 가능성과 소유권을 추측해야 합니다. 모든 인자를 const T&로 받으면 작은 값도 불필요하게 간접 접근하고 수정 의도도 숨습니다. 전달 방식은 빠르다는 소문이 아니라 API의 의미를 표현해야 합니다.

학습 목표​

먼저 알아야 할 핵심 개념​

참조는 일반적으로 이미 존재하는 객체의 별칭으로 사용합니다. 정상적인 참조는 null을 표현하지 않고 다른 객체로 재지정하지 않습니다. 포인터는 주소 값이므로 nullptr를 가질 수 있고 다른 주소를 다시 저장할 수 있습니다. 둘 다 비소유로 사용할 수 있으므로 대상 수명은 별도 계약입니다.

의도추천 형태호출자가 읽는 계약
작은 값 입력int amount독립 값, 수정 영향 없음
필수 읽기 전용 큰 값const Task& task반드시 존재, 복사 없음
필수 수정 대상Task& task반드시 존재, 원본 수정
선택적 비소유 대상Task* tasknull 가능, 소유하지 않음
단일 소유권 이전std::unique_ptr<Task>호출 대상이 소유권을 넘김

왜 이 문제가 위험한가​

선택적 포인터를 검사하지 않으면 null 역참조가 되고, 참조나 포인터를 장기 저장하면 호출자가 먼저 파괴할 수 있습니다. const T&를 멤버로 무심코 저장하는 것도 같은 댕글링 위험이 있습니다. 전달 문법만 맞아도 수명 계약이 틀리면 안전하지 않습니다.

가장 작은 예제로 시작하기​

parameter_contracts.cpp
#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);
}

코드 한 줄씩 이해하기​

  1. raisePriority의 Task&는 원본 수정이 필수임을 표현합니다.
  2. amount는 작은 독립 값이라 값 전달이 단순합니다.
  3. printTask는 필수 읽기 전용 객체를 const Task&로 받습니다.
  4. printSelected는 선택 결과가 없을 수 있어 const Task*를 받습니다.
  5. 어느 raw pointer도 파괴 책임을 갖지 않습니다.

실행 결과와 메모리·동작 흐름​

build.priority는 2에서 3으로 바뀌고 첫 줄에 build:3이 출력됩니다. 두 번째 호출은 대상이 없어 none을 출력합니다. 모든 참조와 포인터는 main의 build 수명 안에서만 사용되고 저장되지 않습니다.

단계별 실습​

흔한 실수와 해결 방법​

언제 사용하고 언제 피할까​

필수 입력은 값 또는 참조, 선택 입력은 포인터, 소유권 이전은 스마트 포인터나 값으로 표현합니다. 성능은 프로파일링으로 확인하되 먼저 호출자가 오해할 수 없는 계약을 만듭니다.

게임 개발 연결​

필수 설정, 수정 대상 상태, 선택된 대상은 서로 다른 API 계약입니다. 엔진과 무관하게 null 가능성과 수명 책임이 시그니처에 보여야 합니다.

이해 점검 질문 3개​

  1. 참조와 포인터가 null 표현과 재지정에서 어떻게 다른가요?
  2. const T&를 클래스 멤버로 저장할 때 어떤 수명 문제가 생길 수 있나요?
  3. 소유권 이전을 raw pointer보다 unique_ptr 값으로 표현하면 무엇이 명확해지나요?

핵심 요약​

다음 강의 연결​

5강. 동적 할당의 문제에서 raw pointer가 소유권까지 맡을 때 생기는 누수와 이중 해제를 분석합니다.

MINI QUIZ

참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계”의 위험한 선택을 피하려면 어떤 원칙을 적용해야 하나요?
  2. 문제 2“참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계”에서 ‘모든 큰 객체를 참조로 저장’ 문제가 생겼습니다. 가장 알맞은 진단 또는 대응은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

4강. 참조와 포인터 선택 기준: 별칭, null 가능성, 함수 인자 설계 미완료 상태