본문 바로가기
책 정리/Effective C++ 3rd

항목 14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자

by ocean20 2019. 12. 30.

우리는 RAII 기법 그리고, Heap 기반 자원에 대해 아이디어를 적용한 auto_ptr, tr1::shared_ptr 클래스에 대해서 공부하였다.

 

Q. 하지만 힙기반 자원이 아닐땐 어떻게 해야할까?

 

A. Mutex 객체를 조작하는 c api 함수인 lock  unlock에대해 살펴보자.

void lock(Mutex *pm); // pm이 가리키는 뮤텍스에 잠금을 건다.

void unlock(Mutex *pm); // pm이 가리키는 뮤텍스 잠금을 해제한다.

 

 

이제 이함수를 관리하는, 뮤텍스 잠금을 관리하는 클래스를 만들어보자.

이런 용도의 클래스는 여태까지 봐온 RAII 법칙을 따라 구성한다.

생성시 -> 자원획득 / 소멸시 -> 자원해제

//뮤텍스 잠금 관리 클래스
class Lock{
public:
  explict Lock(Mutex *pm) : mutexPtr(pm)
{ lock(mutexPtr); }  //자원 획득

~lock() { unlock(mutexPtr); } //자원 해제

private:
  Mutex *mutexPtr;
};
//Lock 클래스 사용방법
Mutex m;  //뮤텍스 정의
…
{  //임계영역의 시작
  Lock m1(&m);  // 뮤텍스의 잠금건다.
  …
}  //임계영역의 끝, 뮤텍스의 잠금이 자동으로 해제된다.

 

Q. 만약 Lock 객체가 복사된다면 어떻게 해야할까?

 

A. 일반적으로 다음과 같은 방법이 있다.(다른방법도 상황에 따라 구현하면된다.)

  (1) 복사 금지

  6장에서 학습한 Uncopyable 사용하여 복사를 금한다.

  (2) 관리하고 있는 자원에 따라 참조카운팅 수행한다.

  tr1::shared_ptr 사용하여 참조카운팅을 수행한다.

  shared_ptr 참조카운팅이 0일때 대상을 삭제해버린다.

  하지만 옵션값을 이용하여 참조카운팅이 0일때 삭제대신 특정한 객체 또는 함수(삭제자라고 부른다.) 호출하도록

  설정할 있다.

  (3) 관리자원을 진짜 복사한다.

  표준 string 보면 힙메모리 공간을 포인터로 참조한다. 이때 복사가 일어날시 포인터도 복사되므로 깊은 복사가 된다.

  (4) 자원의 소유권을 옮긴다.

  auto_ptr 이용해서 자원의 소유자를 하나로 설정이 가능하다.(auto_ptr 복사시 이전 auto_ptr 삭제된다.)

 

이것만은 잊지말자!

  (1) RAII 객체의 복사는 객체가 관리하는 자원의 복사문제를 안기때문에, 특성에 따라 알맞은 복사동작을 결정하면된다

  (2) 일단적인 RAII 복사동작은 복사금지 OR 참조카운팅을 하는선으로 마무리하자.

댓글