[C++] 항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자
카테고리: Cpp
태그: Cpp
이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 GPT에게 요약을 요청하여 작성되었습니다.
이펙티브 C++ 제3판, 스콧 마이어스 저자, 곽용재 번역
📦 3. 자원 관리
👉🏻 항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자
✅ 문제 상황
int priority();
void processWidget(shared_ptr<Widget> pw, int priority);
int main() {
processWidget(new Widget, priority()); // ❌ 컴파일 에러
processWidget(shared_ptr<Widget>(new Widget), priority()); // ✅ 컴파일 가능
}
위 두 번째 줄은 컴파일은 되지만, 문제는 예외 발생 시 자원 누수가 생길 수 있다는 데 있다.
⚙️ 함수 인자 평가 순서가 문제
processWidget(shared_ptr<Widget>(new Widget), priority());
여기서 컴파일러는 다음 3가지 연산을 수행해야 함:
priority()
호출new Widget
실행shared_ptr
생성자 호출
그런데 C++ 표준은 인자 평가 순서를 정의하지 않음.
→ 컴파일러마다 순서가 다를 수 있음
📉 예외 발생 시 누수 가능성
어떤 컴파일러는 아래 순서로 실행할 수도 있다:
new Widget
실행priority()
호출 → 예외 발생!shared_ptr
생성자 호출 ❌ 실행 안 됨
→ 이러면 new Widget
으로 만든 객체가 shared_ptr에 안 들어가고, 누수됨
✅ 안전한 코드
shared_ptr<Widget> pw(new Widget); // 스마트 포인터 생성 먼저!
processWidget(pw, priority()); // 그다음 함수 호출
중간에 예외가 발생해도 pw
가 스마트 포인터에 담겨 있기 때문에, 자원은 누수되지 않음.
🧐 정리
new
로 생성한 객체를 스마트 포인터에 넣는 코드는 한 문장으로 분리하자.- 그렇지 않으면 함수 인자 평가 순서에 따라 예외 발생 시 자원이 누수될 수 있다.
- 항상 먼저 스마트 포인터에 안전하게 담고, 그 뒤에 함수 호출을 하자.
댓글남기기