항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자
먼저 아래 코드를 보자.
int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);
#if 0
processWidget(new Widget, priority()); // 빌드 안됨
// shared_ptr은 암시적 변환 지원 안함
#endif
processWidget(std::shared_ptr<Widget>(new Widget), priority());
1. 마지막 문장에서 processWidget을 호출하기 전에 인자 평가 순서는?
컴파일러 마다 평가하는 순서는 다르다.
인자 평가를 위한 세가지 종류의 코드는 무엇인가?
priority를 호출한다.
new Widget을 실행한다.
- shared_ptr 생성자를 호출한다.
3. 위 코드의 문제점은 뭔가?
인자 평가 순서가 아래와 같다고 가정하자.
- new Widget 실행
- priority 호출
- shared_ptr 생성자 호출
이 상황에서 priority 실행중 예외가 발생되면 shared_ptr의 생성자 호출은 실행되지 않아 new Widget 에서 받은 메모리가 실종된다.(이 경우 디버깅 하기 힘듬)
4. 해결법은?
아래 코드처럼 new 부분은 독립된 한 문장으로 처리한다.
std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
정리
- new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만들자. 이것이 안 되어 있으면, 예외가 발생될 때 디버깅하기 힘든 자원 누출이 될 수 있다.