방프리

17.07.13. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목14) 본문

C++/Effective C++

17.07.13. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목14)

방프리 2020. 1. 8. 04:07

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

 

모든 자원은 힙에서 생성되지 않습니다. 그렇기 때문에 앞의 13항목에서 배운 auto_ptr 이나

tr::shared_ptr의 경우 사용할 수 없다는 큰 제약이 생겨버립니다.

그래서 RAII 객체가 복사가 되거나 관리를 할 때 어떤 조건을 충족해야하는지 알아보겠습니다.

(1) 복사를 금지합니다.

- RAII 객체가 복사되도록 놔두는 것은 말이 안됩니다. 특히 뮤텍스처럼 쓰레드의 동기화를 일으키는 객체의 경우

사본이 있는다는건 더더욱 말이 안됩니다.

이걸 방지하는 방법으로는 복사 함수를 private로 선언해 복사를 막는 방법이 있습니다.

(2) 관리하고 있는 자원에 대해 참조 카운팅을 수행합니다.

- 객체가 복사될 경우 사본을 생성하는 것이 아닌 원본 자체에서 참조 카운팅을 올려주는 방법도 있습니다.

많이 익숙한 방법이죠?

앞의 13항목에서 나왔던 tr::shared_ptr의 내용입니다. auto_ptr의 경우에도 사본을 생성할 경우 원본을

null로 바꾸었기 때문에 적합하지 않아 tr::shared_ptr을 통해 참조카운트 방식으로 사용했던 것을 떠올리시면 됩니다.

하지만 이 클래스도 참조카운팅이 0이 되는 순간 객체를 삭제해버립니다;;

뮤텍스 같은 객체들은 Lock, Unlock만 하면 되지 삭제할 필요까진 없거든요.

하지만 다행이 delete 연산 시 어떤 것을 수행할 지 지정할 수 있습니다. 

(3) 관리하고 있는 자원을 진짜로 복사합니다. 

- 이 부분은 상황에 맞추어 원본 자체를 복사하는 것을 말합니다. 즉, 깊은 복사를 해야한다는 뜻입니다.

(4) 관리하고 있는 자원의 소유권을 옮깁니다.

- 상황에 따라서 RAII 객체를 단 하나만 생성하고 싶을 때 사용합니다.

간단한 예로 auto_ptr의 동작을 이해하시면 될 것 같습니다.

 

이것만은 잊지 말자!

* RAII 객체의 복사는 그 객체가 관리하는 자원의 복사 문제를 안고 가기 때문에, 그 자원을 어떻게 복사하느냐에 따라

RAII 객체의 복사 동작이 결정됩니다.

* RAII 클래스에 구현하는 일반적인 복사 동작은 복사를 금지하거나 참조 카운팅을 해주는 선으로 마무리 하는 것입니다.

하지만 이 외의 방법들도 가능하니 참고해 둡시다.

Comments