본문 바로가기
Language/C++

스마트 포인터 (Smart Pointer)

by W00gie 2021. 12. 17.

스마트포인터는 포인터처럼 활용하는 클래스 템플릿으로 메모리를 자동으로 해제해준다.

일반적으로 동적할당한 메모리는 해제 코드를 작성하지 않을 경우 Memory Leak이 발생하는데, 스마트 포인터는 이를 방지해준다. 이전 C++( 내가 처음으로 접했던 C++ 전공책) 에서는 스마트포인터가 auto_ptr로써 소개되었지만 C++11 이후로는 auto_ptr이 삭제되고, unique_ptr, shared_ptr, weak_ptr 세 가지로 존재한다.

 

* unique_ptr

기본 포인터로 한 명의 소유자만 허용하는 스마트 포인터이다.

새 소유자로 이동할 수 있지만 내부적으로 복사 연산자를 막아놓았기 때문에 move 연산만 가능하다.

 

*shared_ptr

레퍼런스 카운팅을 지원하는 스마트 포인터이다. 레퍼런스 카운팅이란 해당 객체를 참조하고 있는 포인터가 몇개인지 세어준다는 뜻이다. 레퍼런스 카운팅은 컴포넌트 패턴과 같이 한 클래스가 여러 객체를 참조하고 있는 상황에 꼭 필수적인 요소이다. shared_ ptr은 이를 통해 참조중인 객체가 다른 객체의 활동에 의해 해제 되는 상황을 막을 수 있다.

실제 shared_ptr의 내부를 살펴보면 Reference Count를 담당하는 클래스 _Ref_count_base를 확인할 수 있다.

_ref_count_base에서 또 실제 해당 클래스를 사용하는 shared_ptr의 수와 weak_ptr의 수를 따로 카운트함을 알 수 있는데, 이는  *Cycle의 생성을 막기 위함이다.

(Cycle = 레퍼런스 카운트가 0임을 삭제의 조건으로 할때, 서로 참조하는 있는 두 객체가 삭제되기까지 서로의 소멸을 기다려 절대 삭제 되지 않는 경우, 데드락과 유사하다.)

 

*weak_ptr

weak_ptr은 자신이 참조하고 있는 shared_ptr의 상태를 확인할 수 있다. 

다만 위에서 weak_ptr의 수가 레퍼런스 카운트에서 별개로 카운트됨을 확인했듯이 실제 shared_ptr와 같이 액세스 하거나 객체의 생명주기를 다루진 못한다. 다만 참조하고 있는 shared_ptr의 상태를 확인해 해당 메모리가 해제되었는지, 아직 생명주기속에 활용이 가능한 상태인지 확인할 수 있다. 이 과정은 아래 expired 함수를 통해 확인하거나 weak_ptr에 lock을 걸어 확인할 수 있다.

 

bool expired() const
{      
    // return true if resource no longer exists
    return (this->_Expired());
}