갑작 스러운 질문 부터 시작한다.
- 자원을 단순히 관리하고 마지막 try/catch 구문을 덤으로 제거할 수 있는 좀 더 진보적인 기술들을 어떻게 적용할 수 있을까?
- 내재된 데이터형 T의 요구사항을 줄여서 Stack을 개선할 수 있는 방법이 있을까?
- 일반적인 컨테이너에서 예외 설계를 사용할 수 있을까?
- new[]와 delete[]가 정말로 하는 일은 무엇일까?
지금까지 만들어본 Stack 의 주요 예외안전성을 메모리를 관리하는 방법에 그 초점을 두고 있다. 따라서, 이런것만 따로 관리하는 보조클래스를 한쪽에 두는것이 좋을 듯 싶다.
다음 코드를 이런 초점에 맞추어서 만들어진 클래스이다.
자.. 이제 문제의 시간이 돌아왔다.
1. StackImpl의 세개의 멤버 함수 모두를 예전 방식과는 다르게 구현해 보자. 어느 상황에서든지 v_ 버퍼의 컨테이너의 T 개체의 수만큼 많지도 적지도 않게 완전히 같은 T 개체를 담고 있음을 가정하자.
2. StackImpl의 의무사항을 기술해 보자.
3. /* ??? */에 뭐가 들어가야 할까? StackImpl이 사용하게 될 방법에 선택이 미치는 영향이 무엇인지 가능한 구체적으로 말해라.
해결책
1.
생성자
보면 알다 시피, StackImpl 생성자에서 메모리 할당을 한다. 이해하는데 별 무리는 없지만 바로 3라인의 operator new 가 생소해 보일 수도 있다. operator new( size_t ) 를 넣게 되면, T의 생성자 호출 없이 이 메모리 공간만 할당 되어진다.(지금은 이 정도만 알고 넘어가도 된다. 주의해야 할것은 이렇게 생성된 T 타입을 해제하려 할때 명시적으로 T::~T()를 호출해 주어야 한다는 것이다.(나중에 설명할 일이 있을듯) )
이전 항목들에서 배웠듯이 만약 operator new(size_t) 를 호출하는 중 예외가 발생하면 StackImpl 생성자는 온전히 만들어지지 못했으므로 아무것도 아닌게 되고 예외는 StackImpl 생성자의 호출자에게 전가된다. 이것은 예외에 중립적인것을 뜻한다.
소멸자
소멸자는 알다 시피, 예외를 던지지 말아야 한다. operator delete( v_ ) 를 하면 첫번째 메모리만 날라가게 되는데, 이것은 operator new 할때, 메모리가 실질적으로 어디에 생성되는지 안다면 이렇게 해도 된다는 것을 알것이다. 단지 T 타입의 소멸자를 호출해 주는 로직이 보이지 않는데
그것은 destory 함수에서 v_ 에서 v_+vused_ 까지 루프를 돌면서 알아서 소멸자를 호출해 줄것이다. 물론 T::~T() 소멸자에서도 예외를 던저선 안된다.
Swap
머리속으로 이 코드를 생각해 본다면, 자신이 갖고 있는 모든 것들을 교환 시킨다.(swap 함수는 기본적으로 알것이라고 생각한다). 또한 throw() 로 그 어떤 예외도 던지지 않는 완벽한 보증을 하게 된다. swap 은 단순한 값 교체이므로 예외를 던지지 않는다.
각각의 함수들을 정리해보면, 한가지 규칙에 따른다. "항상 코드의 각 조각에 하나의 잘 정의된 책임감을 부여하자" 이것은 예외 보장에 승리하기 위한 초석이 된다.
그럼 /* ???? */ 으로 주석 처리 된 곳에 public: 이 들어가야 할까? protected 또는 private 이여야
할까?
이 부분은 책의 내용을 보았을 때, 잘 이해가 가지 않는다. - 다시 봐야할 부분 -
총평
각각의 역활을 분배하는것은 예외 보장을 더욱 견고하게 해주는 것을 배운다. 메모리 관리 부분 StackImpl에서 관리하고 각
데이터 관리 부분은 Stack 이 관리 함으로써, 서로 다른곳의 예외에 대해서만 보장을 한다면, 전체적으로 예외에 보장을 할 수 있다는 것을
배웠다.
'책 정리 > Exceptional C++' 카테고리의 다른 글
항목 35 : 메모리 관리 - 파트 1 (난이도 3) (0) | 2008.10.08 |
---|---|
항목 41 : 개체 활동 주기 - 파트 2 (난이도 : 6) (0) | 2008.10.08 |
항목 40 : 개체 활동 주기 - 파트 1 (난이도 : 5) (0) | 2008.10.08 |
항목 39 : 자동 변환 (난이도 : 4) (0) | 2008.10.08 |
항목 38 : 개체의 정체(Object Identity) (난이도 : 5) (0) | 2008.10.08 |
항목 11 : 예외에 안전한 코드를 작성하기 - 파트 4 (난이도 8) (0) | 2008.10.07 |
항목 10 : 예외에 안전한 코드를 작성하기 - 파트 3 (난이도 9½) (0) | 2008.10.07 |
항목 9 : 예외에 안전한 코드를 작성하기 - 파트 2 (난이도 8) (0) | 2008.10.07 |
항목 8 : 예외에 안전한 코드를 작성하기 - 파트 1 (난이도 7) (0) | 2008.10.07 |
예외에 안전한 코드에 대한 생각을 하게된 폭팔적인 계기 (0) | 2008.10.07 |
최근댓글