스콧 마이어스의 Effective C++을 읽고 개인 공부 목적으로 요약 작성한 글입니다!
💡 RAII 객체의 복사는 그 객체가 관리하는 자원의 복사문제를 안고 가기 때문에,
그 자원을 어떻게 복사하느냐에 따라 RAII 객체의 복사 동작이 결정된다!
💡 RAII 클래스에 구현하는 일반적인 복사 동작은 복사를 금지하거나, 참조 카운팅을 해주는 것이다.
이외에도 진짜 복사하기, 소유권 이전하기 등도 가능하긴 하다..!
void lock(Mutex* pm);
void unlock(Mutex* pm);
class Lock {
public:
explicit Lock(Mutex* pm) : mutexPtr(pm) { lock(mutexPtr); }
~Lock() { unlock(mutexPtr); }
private:
Mutex* mutexPtr;
};
이런 큐텍스를 조작하는 관리 클래스를 만든다고 치면,
RAII 법칙을 따라 생성 시 자원을 획득하고, 소멸시 그 자원을 해제하도록 만들어야 한다.
이러한 객체를 RAII 객체라고 하자
Mutex m;
Lock m11(&m);
Lock m12(m11);
이 상황은 어떻게 해야 하냐?
RAII 객체를 복사 금지로 만든다.
그냥 아예 안된다고 막는다.
스레드 동기화 객체와 같은 상황에서는 사본이 만들어지면 안되니까!
class Lock : private UnCopyable {
public:
...
}
무느알?
UnCopyable과 같이,, (항목 6 참고)
복사 생성자, 복사 대입 연산자를 private으로 선언해놓고 정의하지 않은 기본 클래스로부터 상속받자
shared_ptr처럼!!
해당 자원을 참조하는 객체의 개수에 대한 카운트를 증가시키는 방식으로 복사를 수해하도록 두자.
근데 shared_ptr가 이렇게 동작하니까
클래스의 Mutex* mutexPtr
을 std::tr1::shared_ptr<Mutex> mutexPtr
로 만들고 싶자나
근데
shared_ptr는 참조 카운트가 0이 될 때 자신이 가리키고 있는 대상을 삭제해버린다
우리는 unlock만 하면 되는데 굳이 얘는 삭제를 시킨다는 거지
근데!!
뭔소리냐면
일단
삭제자
: shared_ptr가 유지하는 참조 카운트가 0이 되었을 때 호출되는 함수 (혹은 함수 객체)
그니까 참조 카운트가 0이 되었을 때 하고 싶은 동작 지정이 가능하다는거다!!
(auto_ptr는 이런 기능 없음. 그냥 포인터 바로 삭제해버림)
개꿀
class Lock {
public:
explicit Lock(Mutex* pm) : mutexPtr(pm, unlock) { lock(mutexPtr.get()); }
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
};
이렇게 되니까 굳이 소멸자를 선언해줄 필요가 없다.
클래스의 소멸자는 비정적 데이터 멤버의 소멸자를 자동으로 호출해준다.
mutexPtr는 비정적 데이터 멤버니까
mutexPtr의 소멸자는 참조 카운트가 0이 되면 unlock을 자동으로 호춣래줄거다.
진짜로 걍 복사해버린다
깊은 복사 (deep copy)로 조져버린다
하고 싶다는 대로 복사 해주고, 자원을 다 썼으면 각각의 사본을 다 해제해주기만 하자.
예를 들어서 표준 string 타입이라 치면,
문자열을 구성하는 원소들을 힙 메모리에 저장해놓고,
이 메모리에 대한 포인터를 데이터 멤버로 갖는다.
-> 결국 힙 메모리를 포인터로 물고 있는 형태!!
이 객체를 복사하면,
포인터와 그 포인터가 가리키는 새로운 힙 메모리를 가지게 된다.
이게 깊은 복사다!
auto_ptr 처럼!!
특정 자원에 대해 그 자원을 실제로 참조하는 RAII 객체는 딱 하나만 존재하도록 만드는 거다
RAII 객체가 복사될 때 그 자원의 소유권을 사본으로 그냥 옮겨준다.
😊 느낀점
자원 관리 클래스,,
재작년쯤 스마트포인터의 복사 문제를 실제로 겪었던 적이 있다
사실 unique_ptr에 대한 이해를 전혀 못하고 그냥 갖다가 썼다가 난리를 친 경험이지만..
그래서 좀 열심히 읽었다
생각해보고, 또 생각해보고!
컴파일러가 만들어주는 소멸자를 자동으로 호출되게
이런 부분은 진짜 ,,
난 바보고 이 사람들은 천재구나 싶어
ㅠㅠ