일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- lua
- 게임
- UE4
- Smart Pointer
- operator new
- c++
- 반복자
- effective stl
- 영화
- 암시적 변환
- 비교 함수 객체
- more effective c++
- exception
- 참조자
- implicit conversion
- Vector
- 다형성
- 티스토리챌린지
- 상속
- 오블완
- 루아
- 예외
- 스마트 포인터
- virtual function
- resource management class
- 언리얼
- 메타테이블
- 영화 리뷰
- Effective c++
- reference
Archives
- Today
- Total
스토리텔링 개발자
[More Effective C++] 13. catch 매개변수는 참조자 본문
728x90
항목 13. 발생한 예외는 참조자로 받아내자
catch 매개변수를 포인터로(catch-by-pointer)
- 이론 상으로는 포인터로 받는 것이 가장 효율적이어야 한다.(항목 15 참조)
- 객체의 복사 없이도 전달이 이루어지기 때문이다.
class exception { ... };
void someFunction()
{
static exception ex; // 범위를 벗어나도 살리기 위해 static 선언
// exception ex; // 이처럼 선언하기라도 하면 미정의 동작을 유발한다!!
...
throw &ex; // 포인터 객체를 던진다.
...
}
void doSomething()
{
try
{
someFunction();
}
catch(exception* ex) // exception*를 받는다.
{
...
}
}
- 힙 객체를 새로 만들고, 그 객체를 예외로 던지는 방식은 어떨까?
void someFunction()
{
...
throw new exception; // 괜찮은 것 같지만..
// 1. operator new가 예외를 발생시키면 어쩌나?
// 2. 힙에 할당한 메모리는 누가 해제해주나?
...
}
- 예외를 받는 측에서는 모순이 발생한다.
- 힙에 할당한 메모리의 포인터인지 아닌지 알 방도가 없으므로 delete 할지 말지 결정할 수 없다.
- static이나 전역 변수의 포인터에 대해 delete를 하면 큰일이다.
- 또 하나의 문제
catch 매개변수를 값으로(catch-by-value)
- 효율
- 늘 두 번씩 복사되기 때문에 비효율적이다.(항목 12 참조)
- 슬라이스 문제(slicing problem)
- 파생 클래스 객체가 기본 클래스를 받는 catch문에 들어가면?
- 파생 클래스 부분이 잘려나간다.(sliced off)
- 이 문제는 찾아내기 무척 까다롭다.
- 파생 클래스 객체가 기본 클래스를 받는 catch문에 들어가면?
class exception
{
public:
virtual const char* what() throw();
...
};
class runtime_error : public exception { ... };
class Validation_error : public runtime_error
{
public:
virtual const char* what() throw(); // exception의 것을 재정의
...
};
void someFunction()
{
...
if(유효성 검사가 실패한다면)
{
throw Validation_error();
}
...
}
void doSomething()
{
try
{
someFunction();
}
catch(exception ex)
{
cerr << ex.what(); // 슬라이스 문제!!
// exception::what()이 호출된다.
// Validation_error::what()은 절대 호출되지 않는다.
...
}
}
catch 매개변수를 참조자로(catch-by-reference)
- 모든 것이 행복하다.
- 포인터로 받을때와 비교하면,
- 객체 삭제에 대한 고민이 필요 없다.
- C++ 표준 예외를 처리할 수 있다.
- 값으로 받을때와 비교하면,
- 예외 객체는 한 번만 복사된다.
- 슬라이스 문제가 없다.
void someFunction()
{
...
if(유효성 검사 실패 시)
{
throw Validation_error();
}
...
}
void doSomething()
{
try
{
someFunction();
}
catch(exception& ex) // 단지 &를 붙였을 뿐인데..
{
cerr << ex.what(); // Validation_error::what()를 호출한다!!
...
}
}
참조
728x90
'개발 > More Effective C++' 카테고리의 다른 글
[More Effective C++] 15. 예외 처리 비용 (0) | 2024.08.20 |
---|---|
[More Effective C++] 14. 예외 지정(예외 명세) (0) | 2024.08.19 |
[More Effective C++] 12. 예외 전달 vs 함수 매개변수 전달 (0) | 2024.08.14 |
[More Effective C++] 11. 소멸자 예외 처리 (0) | 2024.08.13 |
[More Effective C++] 10. 생성자 예외 처리 (0) | 2024.08.12 |
Comments