C++ 공부

C++언어 기초 - 5. 자원 관리하기

Client Side 2025. 8. 26. 12:21

메모리는 한정된 자원이다.

스택 메모리

  • 일반 변수는 대부분 스택 메모리 공간을 차지한다.
  • 변수의 생존 주기가 끝나면 ( 끝나는 ' } ' 를 만나면 ) 할당된 메모리가 자동으로 회수된다.
  • 크기가 제한적이다.
  • 자동으로 메모리가 회수되기 때문에 더 길게 메모리를 관리하기가 어렵다.

힙 메모리

  • 스택보다 큰 메모리를 가진다.
  • 동적 할당 시 new 연산자를 사용하고, 해제 시 delete 연산자를 사용한다.
  • new 연산자
    • 주소값을 반환한다. -> 포인터로 받는다.
    • new int[5] 로 할당을 했다면  delete[ ] 로 메모리를 해제해줘야 한다. 배열로 시작했으면 배열로 끝내야 한다.
  • 스택메모리는 코드 실행 전에 메모리를 할당해야 하는데, 힙메모리는 코드 실행과 동시에 메모리를 할당할 수 있다.

Dangling Pointer

  • 이미 해제된 메모리의 주소를 계속 가지고 있는 포인터

메모리누수 (Memory Leak)

  • 사용하지 않는 영역을 해제하지 않고 계속해서 메모리 할당을 하다보면, 더 이상 사용 가능한 메모리가 없을 수 있다.
  • Heap은 여러가지 장점이 있지만, 메모리를 직접 관리해야 하는 부담이 있다. 위의 문제가 발생할 수도 있다.
  • 그래서 C++에서는 이를 해결하기 위해 스마트 포인터를 제공한다.

 

스마트 포인터 ( #include <memory> )

1. unique_ptr

  • 객체에 대한 단일 소유권을 관리한다. 동시에 두개의 포인터가 하나의 공간을 소유할 수 없다.
  • move를 통해 소유권을 이동하는 식으로 관리된다.

2. shared_ptr

  • 여러개의 포인터로 하나의 공간을 소유할 수 있다.
  • 그렇기 때문에 현재 객체를 참조하는 포인터의 개수를 카운팅하는 레퍼런스 카운트를 관리한다.
  • 레퍼런스 카운트가 0이 되면 자동으로 메모리 해제.
  • 이를 활용하여 Dangling Pointer 및 MemoryLeak 문제를 효과적으로 방지할 수 있다.

3. weak_ptr

  • 객체의 소유권을 공유하지 않는다.
  • 다른 스마트포인터와 다르게 레퍼런스 카운트를 증가시키지 않는 약한 참조를 한다.
  • shared_ptr는 유용하지만 순환참조가 발생할 수 있다. (순환참조 : 두 개 이상의 객체가 서로를 shared_ptr로 가리켜 참조하는상황)
  • shared_ptr은 관찰과 소유를 하는반면, weak_ptr은 관찰만 한다고 표현한다.

 

unique_ptr

  • 객체 소유권을 관리하는 스마트 포인터. 단 하나의 포인터만 객체를 소유할 수 있다.
  • 소유권의 개념만 있기 때문에 복사 혹은 대입이 불가능하다.
  • 복사가 불가능하며 move를 사용해서 소유권 이전만 가능하다.

weak_ptr

  • 레퍼런스 카운트에 영향을 미치지 않는 약한 참조이므로, 반드시 lock()함수로 내부 객체 유효성을 확인하고 사용해야 한다.

 

얕은 복사와 깊은 복사

얕은 복사

  • 클래스 내의 포인터 멤버를 복사할 때 포인터가 가리키는 데이터가 아닌 포인터가 저장하고 있는 주소값만 복사하는 것.

깊은 복사

  • 클래스의 포인터 멤버가 가리키는 동적 데이터를 새로 할당된 독립적인 메모리 영역에 복제하는 것.