[C++] 항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자
카테고리: Cpp
태그: Cpp
이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
이펙티브 C++ 제3판, 스콧 마이어스 저자, 곽용재 번역
📦 3. 자원 관리
👉🏻 항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자
자원은 꼭 힙에 만들 필요는 없다.
뮤텍스(Mutex) 처럼 C API로 관리하는 자원은 스마트 포인터보단 직접 관리 클래스를 만드는 게 낫다.
void lock(Mutex* pm); // 잠금
void unlock(Mutex* pm); // 해제
✅ RAII 스타일로 자원 관리
class Lock {
public:
explicit Lock(Mutex *pm) : mutexPtr(pm) {
lock(mutexPtr);
}
~Lock() {
unlock(mutexPtr);
}
private:
Mutex *mutexPtr;
};
- 생성 시 자원을 잠그고
- 소멸 시 자원을 해제한다
→ RAII 스타일로 예외에도 안전하게 동작한다.
❓ 복사를 시도하면?
Lock m11(&m);
Lock m12(m11); // 복사해도 되나?
RAII 객체는 자원에 따라 복사 허용 여부가 달라진다.
1️⃣ 복사 금지
뮤텍스처럼 동기화 자원은 복사하면 위험하다.
→ Uncopyable
상속 등으로 복사를 아예 막는 게 일반적이다.
(항목 6 참고)
2️⃣ 참조 카운팅 (shared_ptr
)
자원을 여러 객체가 공유해야 한다면,
shared_ptr
로 참조 카운팅하면서
삭제자만 잠금 해제 함수로 지정하면 된다.
shared_ptr<Mutex> ptr(pm, unlock);
→ 참조 카운트가 0이 될 때 unlock
호출
→ RAII에 따라 자동 해제됨 (항목 5 관련)
3️⃣ 깊은 복사
자원을 진짜로 복사해야 하는 상황이면
→ 깊은 복사(deep copy)를 구현해서
각 객체가 자기 자원만 책임지도록 해야 한다.
4️⃣ 소유권 이전 (Move)
복사 대신 소유권 이전(move) 만 허용하고 싶다면
→ unique_ptr
처럼 이동만 가능한 방식으로 구현하면 된다.
(예전엔 auto_ptr
이 이런 방식)
🧐 정리
- RAII 객체 복사 허용 여부는 관리 자원에 따라 다르다.
-
일반적인 대응 방식:
- 복사 금지
- 참조 카운팅
- 그 외 대응: 3. 깊은 복사 4. 소유권 이전
→ 상황에 따라 복사 가능성 여부와 방식 모두 신중히 결정해야 한다.
댓글남기기