스마트 포인터 입문: unique_ptr를 우선 고려하는 이유
18강. 스마트 포인터 입문: unique_ptr를 우선 고려하는 이유
이번 강의에서 해결할 문제
new로 만든 객체를 raw pointer에 보관하면 누가 delete해야 하는지 타입에 표시되지 않습니다. 여러 반환 경로에서 삭제가 빠지거나 두 코드가 모두 소유자라고 생각해 이중 해제할 수 있습니다.
학습 목표
unique_ptr가 동적 객체를 단독 소유함을 설명합니다.make_unique로 객체를 만들고 자동 정리를 확인합니다.- 복사 대신 이동으로 소유권을 전달합니다.
먼저 알아야 할 핵심 개념
std::unique_ptr<T>는 T 객체의 단일 소유자입니다. 복사할 수 없고 이동할 수 있습니다. 소유 포인터가 파괴되면 보유 객체도 자동 삭제됩니다. 공유가 요구사항으로 증명되지 않았다면 가장 단순한 값 객체 또는 unique_ptr부터 고려합니다.
가장 작은 실행 가능한 예제
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
class Inventory {
public:
void add(const int itemId) { itemIds_.push_back(itemId); }
std::size_t size() const { return itemIds_.size(); }
private:
std::vector<int> itemIds_;
};
int main() {
auto inventory = std::make_unique<Inventory>();
inventory->add(10);
inventory->add(20);
auto ownedInventory = std::move(inventory);
std::cout << ownedInventory->size() << ' '
<< std::boolalpha << (inventory == nullptr) << '\n';
}
핵심 코드 줄별 설명
make_unique가 객체 생성과 소유 포인터 구성을 한 표현으로 처리합니다.->로 소유 객체의 멤버를 호출합니다.std::move는 소유권 이전이 가능한 값으로 변환합니다.- 이동 뒤 새 포인터가 객체를 소유합니다.
- 원래
inventory는 빈 상태이며 역참조하면 안 됩니다.
실행 결과와 값 변화
2 true
ownedInventory가 범위를 벗어나면 Inventory가 자동 삭제됩니다. 이동 뒤 원래 포인터에 새 객체를 다시 대입하는 것도 가능합니다.
단계별 실습
실습 목표
단일 플레이어가 소유하는 장비 객체를 안전하게 생성·이동합니다.
시작 전 상태와 실행 방법
이름을 가진 Equipment 클래스를 만들고 C++17 프로젝트에 <memory>를 포함합니다.
1단계: 최소 코드 작성
make_unique<Equipment>로 검을 만들고 이름을 출력합니다.
2단계: 값 또는 조건을 바꿔 결과 비교
다른 unique_ptr로 이동한 뒤 원본이 null인지 확인합니다.
3단계: 작은 기능 확장
unique_ptr<Equipment>를 받아 소유권을 플레이어에게 전달하는 함수를 작성합니다.
4단계: 스스로 해결하기
동적 할당 없이 값 멤버로 보관할 수 있다면 어느 쪽이 더 단순한지 비교하고 불필요한 포인터를 제거하세요.
막혔을 때
복사 생성자가 삭제되었다는 오류는 단일 소유권을 복사하려 했다는 뜻입니다. 정말 소유권을 넘길 때만 std::move를 사용하고, 관찰만 필요하면 참조나 raw pointer를 짧게 전달합니다.
흔한 실수와 해결 방법
- 모든 객체를 unique_ptr로 만듦: 동적 수명이나 다형성 필요가 없으면 값이 더 단순합니다.
- 이동 후 역참조: 원본은 null일 수 있으므로 새 소유자만 사용합니다.
- get() 결과를 별도 소유자로 취급: 반환 raw pointer는 관찰자이며 delete하지 않습니다.
게임 개발 연결
표준 C++ 게임 도구의 전략 객체나 선택적 하위 시스템을 단독 소유할 때 적합합니다. Unreal의 UObject는 GC 수명 규칙을 따르므로 std::unique_ptr<UObject>로 소유하지 않으며, 일반 C++ 타입에는 TUniquePtr 또는 프로젝트 규칙을 확인합니다.
이해 점검 질문 3개
- unique_ptr를 복사할 수 없는 이유는 무엇인가요?
- 이동 뒤 원래 포인터는 어떻게 다뤄야 하나요?
- 값 멤버가 unique_ptr보다 더 좋은 선택일 수 있는 경우는 언제인가요?
핵심 요약
unique_ptr는 동적 객체의 삭제 책임을 한 소유자에 고정합니다. 값으로 충분한지 먼저 확인하고, 동적 단일 소유가 필요할 때 make_unique와 이동을 사용합니다.
다음 강의 연결
19강. 값·참조·포인터 기준에서 소유가 아닌 함수 호출 관계를 가장 단순한 인자 타입으로 표현합니다.
스마트 포인터 입문: unique_ptr를 우선 고려하는 이유 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.