반응형
0. 요약
- 자원 관리 객체에서 자원을 관리하자.(RAII 사용)
- 자원 관리 객체는 소멸자에서 해당 자원을 해제 하자!
1. 메모리가 누수될 수 있는 상황 가정
- 구현한 내용
- 투자를 모델링한 기본 클래스 Investment
- Investment 계열의 클래스를 반환하는 팩토리 함수 createInvestment
- 사용부
- createInvestment를 이용해 Investment 계열 클래스 생성
- 사용 후 객체 반환(delete)
- 문제 사항
- 삭제 전에 return 문이 있을 경우
- 삭제 전에 goto문에 의해 루프를 빠져 나갈 경우
- 삭제 전에 예외가 던져질 경우
// 투자를 모델링한 기본 클래스
class Investment{...};
// Invesment를 상속한 클래스를 return하는 팩토리 함수
Invesment* createInvestment();
void f(){
Invesment *pInv = createInvestment();
...
delete pInv;
}
2. 해결 방안
- 자원을 획득한 후에 자원 관리 객체에게 넘기자!
- createInvestment를 통해 만든 자원을 auto_ptr에게 넘겨 초기화하는데 사용
- RAII라고 불림
- 자원 획득과 자원 관리객체의 초기화가 한문장에서 이루어지는 것이 일상적임
- 자원 관리 객체는 자신의 소멸자를 사용해 자원이 확실히 해제되도록 하자!
- 소멸자는 객체가 소멸될 때 자동으로 호출됨
- 소멸자가 호출될 때 자원을 해제하면 자동으로 확실히 해제됨
- 단, 예외가 발생하면 꼬이지만 항목8에서 해결할 예정
- 예제(스마트 포인터)
void f(){
std::unique_ptr<Investment> pInv(createInvesment());
//책에서는 auto_ptr로 예제를 들었으나, C++11에서 unique_ptr로 대체됨
}
3. 스마트 포인터
unique_ptr
- 자원에 대해 유일한 소유권을 가짐
- unique_ptr을 복사 또는 대입하면, 기존 unique_ptr은 null로 변경됨
std::unique_ptr<Invesment> pInv1(createInvesment());
std::unique_ptr<Invesment> pInv2(pInv1); // pInv1 = null로 할당됨
pInv1 = pInv2; // pInv2 는 null로 할당됨
- shared_ptr
- 참조 카운팅 방식 스마트 포인터(RCSP:Reference-Counting Smart Pointer)
- 자원을 가리키는 외부 객체 개수를 확인하다가 0이 되면 자원을 자동으로 삭제함
std::shared_ptr<Investment> pInv1(createInvestment());
std::shared_ptr<Investment> pInv2(pInv1); // pInv1과 pInv2는 같은 객체를 가리킴
pInv1 = pInv2; // 위와 동일ㅈ
참고
- Effective C++
별첨
- RAII(Resource Acquisition Is Initialization)
- 생성자에서 리소스를 획득하고 해당 소멸자에서 해제하는 것!
- 주로 포인터, 뮤텍스 등의 자원의 소멸이 누락되어 발생되는 문제를 방지하기 위해 별도의 자원 관리 객체를 두고, 객체 생성시 자원 획득 및 소멸시 자원 해제하는 것을 얘기함
- RAII 클래스 예시
- string, vector, thread, unique_ptr, shared_ptr, lock_guard, unique_lock, shared_lock
반응형
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 15. 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자 (0) | 2021.03.15 |
---|---|
[Effective C++] 14. 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자. (0) | 2021.03.15 |
[Effective C++] 12. 객체의 모든 부분을 빠짐없이 복사하자 (0) | 2021.03.15 |
[Effective C++] 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 (0) | 2021.03.15 |
[Effective C++] 10. 대입 연산자는 *this의 참조자를 반환하게 하자 (0) | 2021.03.15 |