diff --git a/EffectiveC++/Item29.md b/EffectiveC++/Item29.md index 74e758f..f00aaa2 100644 --- a/EffectiveC++/Item29.md +++ b/EffectiveC++/Item29.md @@ -1,4 +1,4 @@ -## Item 29: 예외 안정성이 확보되는 그날 위해 싸우고 또 싸우자! +## Item 29: 예외 안정성이 확보되는 그날 위해 싸우고 또 싸우자 ```cpp class PrettyMenu { @@ -48,4 +48,41 @@ void PrettyMenu::changeBackground(std::istream& imgSrc) - **예외불가 보장(nothrow guarantee)** - 예외를 절대로 던지지 않겠다는 보장이다. 약속한 동작은 언제나 끝까지 완수하는 함수라는 뜻이다. 기본 제공 타입에 대한 모든 연산은 예외를 던지지 않게 되어 있다. (즉, 예외불가 보장이 제공된다.) 예외에 안전한 코드를 만들기 위한 가장 기본적이며 핵심적인 요소이다. -**앞서 말한 예외 안전성을 갖춘 함수는 위의 세 가지 보장 중 하나를 반드시 제공해야 한다. 아무 보장도 제공하지 않으면 예외에 안전한 함수가 아니다.** \ No newline at end of file +**앞서 말한 예외 안전성을 갖춘 함수는 위의 세 가지 보장 중 하나를 반드시 제공해야 한다. 아무 보장도 제공하지 않으면 예외에 안전한 함수가 아니다. 대부분의 경우 기본적인 보장과 강력한 보장중에 선택하게 된다.** + +```cpp +class PrettyMenu { + ... + std::tr1::shared_ptr bgImage; + ... +}; + +void PrettyMenu::changeBackground(std::istream& imgSrc) +{ + Lock ml(&mutex); + + bgImage.reset(new Image(imgSrc)); + + ++imageChanges; +} +``` + +이 코드를 보면 RAII기법과 같이 이전의 배경 그림을 프로그래머가 직접 삭제할 필요가 없다. 배경그림이 스마터 포인터에 의해 관리되고 있기 때문이다. *이렇게 예외 안전성을 보장한다.* + +다만 매개변수인 imgSrc는 Image클래스의 생성자를 실행하다. 에외를 일으킬 때, 그 시점에 입력 스트림의 읽기 표시자가 이동한 채로 남아있을 가능성이 충분히 있다. 이 문제를 해결하기 전까지 `changeBackground` 함수는 예외 안정성은 기본적인 보장이다. + +### 복사 후 맞바꾸기(copy-and-swap) 기법 + +복사 후 맞바꾸기 기법은 일반적인 함수를 강력한 예외 안전성을 제공하는 함수로 만드는 설계 전략이다. **어떤 객체를 수정하고 싶다면 그 객체의 사본을 만들어 놓고 그 사본을 수정하는 것이다.** 이렇게 되면 동작 중에 실행되는 연산에서 예외가 던져지더라도 원본 객체는 바뀌지 않은 채로 남아 있는 것이다. + +'진짜' 객체의 모든 포인터를 별도의 구현 객체에 넣어두고, 그 구현 객체를 가리키는 포인터를 진짜 객체가 물고 있게 하는 식으로 구현한다. + +이러한 강력한 예외를 보장하는 함수가 있더라도 side effect가 없는 함수로서 존재해야 한다. 이는 함수의 중첩이나 앞서 설명한 다른 함수에 의한(예외) 연쇄작용이 없어야 한다는 뜻이다. + +### 정리 + +새로운 함수를 만들거나 기존의 코드를 고칠 때는 '어떻게 하면 예외에 안전한 코드를 만들까?'를 진지하게 고민하는 버릇을 들여야 한다. *최근에는 Rule of Zero를 따르는 것이 좋다.* + +- 예외 안정성을 갖춘 함수는 실행 중 예외가 발생되더라도 자원을 누출시키지 않으며 자료구조를 더럽힌 채로 내버려 두지 않는다. 이런 함수들이 제공할 수 있는 예외 안정성 보장은 기본적인 보장, 강력한 보장, 예외 금지 보장이 있다. +- 강력한 예외 안정성 보장은 '복사 후 맞바꾸기' 방법을 써서 구현할 수 있지만, 모든 함수에 대해 강력한 보장이 실용적인 것은 아니다. +- 어떤 함수가 제공하는 예외 안전성 보장의 강도는, 그 함수가 내부적으로 호출하는 함수들이 제공하는 가장 약한 보장을 넘지 않는다.