Post
항목13에서 본 shared_ptr(auto_ptr은 이후에 삭제되었다고한다)은 힙이 아닌 다른 자원에는 맞지않다라는 견해가 일반적이다.
하지만 모든 자원이 힙에서 생기지는 않는다. 그래서 자원 관리 클래스를 우리가 스스로 만들어야할 필요성이 있다.
class Lock{
public:
explicit Lock(Mutex *pm)
:mutexPtr(pm)
{ lock(mutexPtr);}
~Lock() {unlock(mutexPtr);}
private:
Mutex *mutexPtr;
};
잠금을 관리하는 클래스를 하나 만들고 , RAII법칙을 따라한다고하자.
Lock m11(&m);
Lock m12(m11);
하지만 여기서 복사를 하게 된다면 어떻게 될까?
복사할때 이루어지는 동작과 관련해서 선택지를 고를 수 있다.
1. 복사를 금지한다.
복사하면 안되는 RAII클래스(위와 같은 Lock)의 경우에는 복사가 아예 안되도록 막아놓아야한다.
이 경우에는 복사함수를 private 멤버로 만들면된다.
2. 관리하고 있는 자원에 대해 참조 카운팅을 수행한다.
해당 자원을 참조화는 객체의 개수에 대한 카운트를 증가시키는 식으로 RAII 객체의 복사 동작을 만들어야한다.
shared_ptr이 이러한 방식을 사용하고있다.
하지만, shared_ptr의 경우에는 참조카운트가 0이되면 삭제가 되기때문에 Lock을 해제만 하고싶지 삭제를 하고싶지않은 사람에게는 다소 목적이 안맞을 수 있다.
class Lock {
public:
explict Lock(Mutex *pm)
:mutexPtr(pm, unlock) //삭제자로 umlock함수 사용
{
lock(mutexPtr.get());
}
private:
std::tr1::shared_ptr<Mutex> mutexPtr; //원시포인터 대신, shared_ptr사용
};
이런경우에는 shared_ptr에 '삭제자'(deleter)라는 것이 있다. 삭제자란 shared_ptr의 참조 카운트가 0이되면 호출되는 함수 혹은 함수객체를 일컫는 말이다. 이 삭제자를 shared_ptr 생성자의 두번째 매개변수에다가 선택하여 넣어줄 수가 있다.
이러면 소멸자를 선언할 필요 없이 비정적데이터 멤버(mutexPtr)의 소멸자가 자동으로 호출되는데, mutexPtr의 소멸자는 shared_ptr의 삭제자가 자동으로 호출되어진다!
3. 관리하고 있는 자원을 진짜로 복사한다.
자원관리 객체를 복사하면 그 객체의 자원까지 복사되어야하기때문에 깊은 복사를 수행해야한다.
4. 관리하고 있는 자원의 소유권을 옮긴다.
'STUDY > Effective C++' 카테고리의 다른 글
항목 13: 자원관리에는 객체가 그만! (2) | 2022.09.22 |
---|---|
항목 12: 객체의 모든 부분을 빠짐없이 복사하자 (0) | 2022.09.08 |
항목 11: operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 (0) | 2022.08.31 |
항목 10 : 대입 연산자는 *this의 참조자를 반환하게 하자 (0) | 2022.08.24 |
항목 9 : 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 (0) | 2022.08.17 |