본문 바로가기
프로그래밍/C++

C++ 스마트 포인터 unique_ptr에 대해서 알아보자

by bantomak 2026. 1. 2.
반응형

unique_ptr 객체는 스택(stack)에 살아요

스마트 포인터인 unique_ptr로 생성한 객체 자체는 스택에 존재한다. 스택에 존재하면서 힙에 할당된 메모리를 관리한다. 이를 C++에서는 RAII(Resource Acquisition Is Initialization) 패턴이라고 부른다.

실제 예제 코드

class MyClass
{
public:
	MyClass() { std::cout << "자원 생성\n"; }
	~MyClass() { std::cout << "자원 소멸\n"; }
};

void main()
{
	{
		std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
	} // <- 이 범위를 벗어나며 소멸함
      // 이때 내부의 ptr도 자동으로 delete함
}
  1. std::unique_ptr<MyClass> ptr 변수가 스택에 생성된다.
  2. std::make_unique가 힙에 메모리를 할당하고 그 주소를 ptr 변수에 담는다.
  3. 이제 스택에 있는 ptr은 힙에 있는 객체의 관리자가 된다.
  4. 블록이 끝나는 순간 스택에 있던 ptr 변수가 메모리에서 제거된다. (소멸자 호출)
  5. 이때 ptr이 관리하고 있던 힙 메모리도 같이 정리된다. (ptr의 죽음의 메아리 효과라고 보면 된다.)

생 포인터(Raw Pointer)를 쓰는 경우

std::unique_ptr을 쓰지 않고 이전 방식인 생 포인터를 쓴다면 어떨까?

{
    MyClass* ptr = new MyClass(); // ptr은 그냥 주소값일 뿐인 '단순 변수'
    // ... 만약 여기서 return이나 예외가 발생해서 아래 delete에 못 가면?
    delete ptr; // 이 코드를 실행해야만 힙이 비워짐
}

이에 반해 unique_ptr은 "스택 변수는 블록이 끝나면 무조건 파괴된다"라는 운영체제의 철칙을 이용하기 때문에 개발자가 깜빡해도 메모리가 안전하게 회수된다.

unique_ptr의 장점

  • 유일한 통제권(Exclusive Ownership)
    • 추적의 용이성: 특정 객체의 상태가 변했다면, 범인은 오직 unique_ptr을 가진 주체뿐이다.
    • 복사 실수 방지: 함수에 인자로 넘길 때 실수로 복사해서 원본이 언제 지워질지 모르게 되는 상황을 컴파일러 단계에서 원천적으로 차단한다.
  • 객체 생명주기와의 동기화(RAII)
    • 자동 파괴: delete를 명시적으로 적지 않아도 객체가 파괴되면 같이 해제됩니다. 잊어버릴 가능성 자체가 사라지게 된다.
    • 예외 안정성(Exception Safety): 코드가 실행되다가 중간에 에러(Exception)가 발생해서 함수가 갑자기 종료되더라도, 스택에 쌓여있던 unique_ptr은 소멸자를 호출하여 힙 메모리를 깨끗하게 제거한다.

unique_ptr은 언제 사용해야하는가?

  • 객체의 크기가 너무 클 때(Stack Overflow 방지)
  • 다형성(Polymorphism)을 활용해야 할 때
  • 객체의 생명 주기를 자유롭게 조절해야 할 때(Life-cycle)

상황에 맞게 선택하기

  • 객체가 작고, 해당 블록 안에서 사용하고 버릴 경우 > 그냥 객체(스택 변수)를 사용하자.
  • 객체가 크거나, 상속 구조가 필요하거나, 소유권을 주고 받아야할 때 > 스마트 포인터 unique_ptr을 사용하자.
  • 여러 곳에서 하나의 객체를 동시에 소유하고 참조해야 할때 > 스마트 포인터 shared_ptr을 사용하자.

정리하자면

  • unique_ptr은 값의 문법(Value Semantics)으로 참조(Reference)를 관리한다.
  • 스택처럼 변수가 선언된 블록이 끝나면 자동으로 정리됨 (Scope-based)
  • 포인터처럼 실제 데이터는 힙에 있어서 크기 제한이 없고, 다형성을 활용할 수 있음
  • 스택 변수처럼 쓰면서 동시에 힙의 장점을 가져가는 말 그대로 아주 똑똑한 포인터

같이 읽으면 좋은 글

 

메모리 구조(Memory Structure)에 대해서

메모리 구조우리가 exe 파일을 실행하면 운영체제는 프로그램에 정의된 명령어(코드)를 바탕으로 메모리에 프로세스를 적재(Load)한다. 그리고 해당 프로세스를 위한 Code, Data, Heap, Stack 영역이 생

jettstream.tistory.com

댓글