방프리

17.07.18. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목17) 본문

C++/Effective C++

17.07.18. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목17)

방프리 2020. 1. 9. 18:33

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

 

하나의 예제 코드를 보고 시작하겠습니다.

int priority();

void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

...

processWidget(new Widget, priority()); 

자 간단한 코드입니다. 객체의 우선순위를 정하는 코드인데 priority() 함수를 통해 각 객체의 우선순위를

알아내고 processWidget을 통해 우선순위에 따라 처리를 하는 함수인 processWidget() 함수를 만들었습니다.

가만 보자 하니 processWidget() 함수에서 매개인자로 Widget 객체 포인터와 우선순위를 받는데 매개 인자를

동적 할당한 후에 매개인자로 넘기고 있습니다.

가독성이 있어보이는 코드이긴 하나 문제점이 있습니다. 바로 메모리 누수와 explicit입니다.

std::tr1::shared_ptr의 생성자는 explicit로 되어 있기 때문에 암묵적으로 변환이 되지 않습니다.

또한 Widget 생성자와 shared_ptr의 생성자 두 개가 같이 호출되기도 하죠

이에 대한 해결책으로 3가지의 연산을 하는 코드를 넣어주어야 합니다.

(1) priority를 호출하고

(2) "new Widget"을 실행합니다.

(3) 마지막으로 tr1::shared_ptr 생성자를 호출합니다.

 

위의 세 가지를 넣어야만 이 문제가 해결이 될텐데... 각 컴파일러가 동작하는 방식은 모두 천차만별입니다.

즉, 언제 어떤게 먼저 실행될 지 각 컴파일러마다 지정한 것이 다르다는 뜻이죠. 

그럼 보편적으로 사용할 수 있는 방법이 있지 않을까요? 밑의 해결책 코드를 보겠습니다.

std::tr1::shared_ptr<Widget> pw(new Widget);

processWidget(pw, priority());

Widget 객체를 생성하자마자 shared_ptr에 넣습니다. 그 후 processWidget()함수를 통해 priority() 함수를 호출하죠.

이렇게 작성한다면 어떠한 컴파일러에서도 이상하게 동작할 걱정을 할 필요가 없습니다.

대입연산이나 기본동작은 거의 비슷하기 때문이죠.

 

이것만은 잊지말자!

* new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만듭시다. 이것이 안 되어 있으면,

예외가 발생될 때 디버깅하기 힘든 자원 누출이 초래될 수 있습니다.

Comments