반응형
0. 요약
- 자원 관리 클래스(RAII 클래스) 만들 때 복사에 대해 고민하자.
- 복사에 대한 선택지는 아래와 같다.
- 복사를 금한다(Mutex)
- 관리하는 자원의 참조 카운팅 수행(shared_ptr)
- 관리하는 자원을 복사(string)
- 관리하는 자원의 소유권을 이전(unique_ptr)
1.뮤텍스 관리 객체 예시
- 뮤텍스 잠금을 관리하는 객체 구현
class Lock{
public:
explicit Lock(Mutex *pm) : mutexPtr(pm){
lock(mutexPtr);
}
~Lock(){
unlock(mutexPtr);
}
private:
Mutex *mutexPtr;
}
- 사용은 RAII 방식으로
Mutex m;
{
Lock m1(&m); // lock
} // 블록이 끝나면 unlock
- 만약 Lock객체가 복사 된다면?
- 사본이 의미가 없기 때문에 복사가 되면 안된다.
2. RAII 객체 복사 구현시 선택지
- 복사를 금지(3.참고)
- 관리하는 자원의 참조 카운팅 수행(4.참고)
- 관리하는 자원을 복사함(5.참고)
- 관리하는 자원의 소유권을 이전함(6.참고)
3. 복사를 금지
- RAII 객체가 복사 되면 안되는 경우 금지
- 위의 Mutex의 경우에서 사용
- 복사 생성자를 금지
4. 관리하는 자원의 참조 카운팅 수행
- 자원을 사용중인 마지막 객체가 소멸될 때 까지 유지해야할 경우(shared_ptr의 경우) 사용
- 방법
- 복사 시에 자원을 참조하는 객체의 개수 카운트를 증가
- 참조 객체 수가 0이되면 자원을 해제하도록 구현
- shared_ptr을 이용하는 방법
- 참조 카운팅 구현하려면 멤버 변수를 shared_ptr로 구현하면 됨
- shared_ptr의 삭제자
- 삭제자(deleter) : 참조 카운트가 0이 되었을 때 호출되는 함수 또는 함수 객체
- shared_ptr은 삭제자 지정(변경)을 허용함
- Mutex 예제에서 shared_ptr을 이용하도록 변경!
- shard_ptr은 참조 개수가 0이 되면 가리키고 있던 대상을 삭제 하기 때문에 Mutex의 예 맞지 않음(Mutex는 다 썻을 때 잠금 해제만 하면 됨)
- 이럴 때 shared_ptr의 삭제자를 사용하면 참조 객체가 0이 될 때 Mutex를 unlock하도록 구현할 수 있음
class Lock{
public:
explicit Lock(Mutex *pm)
: mutexPtr(pm, unlock) // 삭제자로 unlock을 지정
{
lock(mutexPtr.get());
}
private:
shared_ptr<Mutex> mutexPtr;
}
Mutex m;
{
Lock m1(&m); // lock
} // 블록이 끝나면 삭제자(unlock)가 호출
5. 관리하는 자원을 복사함
- 복사가 필요할 경우 복사를 지원(string의 경우)
- 이 때 반드시 깊은 복사를 수행해야함
6. 관리하는 자원의 소유권을 이전
- 자원을 참조하는 RAII 객체를 딱 하나만 만들고 싶을 때 사용(unique_ptr의 경우)
참고
- Effective C++
반응형
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 16. new 및 delete를 사용할 때는 형태를 반드시 맞추자 (0) | 2021.03.15 |
---|---|
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2021.03.15 |
[Effective C++] 13. 자원 관리에는 객체가 그만 (0) | 2021.03.15 |
[Effective C++] 12. 객체의 모든 부분을 빠짐없이 복사하자 (0) | 2021.03.15 |
[Effective C++] 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 (0) | 2021.03.15 |