스마트포인터는 동적 메모리를 관리하는 클래스이다. 일반적인 포인터와 똑같이 사용할 수 있지만 프로그래머가 직접 메모리 해제를 해주어야하는 포인터와 달리 스마트포인터는 알아서 메모리를 해제해준다.
스마트포인터는 3가지 종류가 있다.
1) unique_ptr
unique_ptr<int> ptr1 = make_unique<int>(10);
unique_ptr<int> ptr2(new int(10));
unique_ptr은 위와 같이 사용할 수 있고 unique라는 단어 뜻 그대로 다른 포인터가 해당 객체를 가르킬 수 없다. 그래서 복사도 불가능하다. 따라서 move와 같은 함수를 사용하여 객체의 소유권을 완전히 넘겨주는 식으로만 동작한다.
2) shared_ptr
shared_ptr<int> ptr1 = make_shared<int>(10);
shared_ptr<int> ptr2(new int(10));
shared_ptr도 unique_ptr와 같은 방식으로 사용 가능하다. 전 게시글의 직접 구현한 Shared Pointer은 이미 만들어져 있는 클래스에 대해서는 사용할 수 없었지만 이는 기존의 클래스에 대해서도 사용 가능하다. shared_ptr은 직접 구현도 해보았는데 참조하는 수를 카운트해서 아무도 참조하지 않을 때 소멸시킨다. 위 코드에서 2번째와 같이 new로 만들 경우 [T*] [RefCountBlock*] 이런식으로 2번 메모리를 할당하게 된다. 하지만 make_shared로 만들 경우 [T* | RefCountBlock*] 이렇게 한번에 메모리를 할당하므로 조금 더 효율적인 방식이라고 할 수 있다.
3) weak_ptr
shared_ptr<int> ptr1 = make_shared<int>(10);
weak_ptr<int> ptr2 = ptr1;
weak_ptr은 shared_ptr을 받아서 사용한다. weak_ptr은 그냥 사용할 수 없고
bool expired = ptr2.expired();
ptr1을 받았기 때문에 expired라는 함수를 사용하여 ptr1이 가르키고 있는 객체가 존재하고 있는지 확인을 먼저 한 후 사용해야 한다.
shared_ptr<int> ptr3 = ptr2.lock();
또는 이처럼 다시 shared_ptr로 캐스팅을 한 후 사용해야 한다. 만약 객체가 소멸되었다면 ptr3는 nullptr이 된다.
weak_ptr은 shared_ptr이 참조하고 있는 객체를 똑같이 가르키긴 하지만 shared_ptr의 RefCount는 증가하지 않는다. 그렇기 때문에 해당 객체의 수명 주기에 영향을 주지 않는다. 따라서 순환 문제가 발생하더라도 한 객체를 weak_ptr로 가지고 있으면 간단하게 문제를 해결할 수 있다.
'서버 > 메모리 관리' 카테고리의 다른 글
6. Memory Pool #1 (0) | 2024.08.20 |
---|---|
5. STL Allocator (0) | 2024.08.16 |
4. Stomp Allocator (0) | 2024.08.16 |
3. Allocator (0) | 2024.08.11 |
1. Reference Counting (0) | 2024.08.09 |