[C++] 항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자

업데이트:     Updated:

카테고리:

태그:

이 글은 아래의 책을 자세히 정리한 후, 정리한 글을 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가지 연산을 수행해야 함:

  1. priority() 호출
  2. new Widget 실행
  3. shared_ptr 생성자 호출

그런데 C++ 표준은 인자 평가 순서를 정의하지 않음.
→ 컴파일러마다 순서가 다를 수 있음


📉 예외 발생 시 누수 가능성

어떤 컴파일러는 아래 순서로 실행할 수도 있다:

  1. new Widget 실행
  2. priority() 호출 → 예외 발생!
  3. shared_ptr 생성자 호출 ❌ 실행 안 됨

→ 이러면 new Widget으로 만든 객체가 shared_ptr에 안 들어가고, 누수됨


✅ 안전한 코드

shared_ptr<Widget> pw(new Widget);  // 스마트 포인터 생성 먼저!
processWidget(pw, priority());      // 그다음 함수 호출

중간에 예외가 발생해도 pw가 스마트 포인터에 담겨 있기 때문에, 자원은 누수되지 않음.


🧐 정리

  1. new로 생성한 객체를 스마트 포인터에 넣는 코드는 한 문장으로 분리하자.
  2. 그렇지 않으면 함수 인자 평가 순서에 따라 예외 발생 시 자원이 누수될 수 있다.
  3. 항상 먼저 스마트 포인터에 안전하게 담고, 그 뒤에 함수 호출을 하자.

Cpp 카테고리 내 다른 글 보러가기

댓글남기기