방프리

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

C++/Effective C++

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

방프리 2020. 1. 8. 04:05

항목 13 : 자원 관리에는 객체가 그만!

 

C++에서는 메모리가 할당되면 당연히 메모리를 해제하는 코드도 넣어주어야 합니다. 기초 중에 기초죠.

(여담으로 C#, Java의 경우엔 가비지 컬렉터가 있으니...)

이 항목에서 말하는 핵심 내용은 이 메모리의 할당 및 해제는 객체 자기 스스로가 해야한다는 것 입니다.

스택에 쌓인 메모리는 일정 범위(지역 함수 및 main 함수이겠죠)를 넘어가면 자동으로 해제가 됩니다. 

만약 이 자원을 관리하는 주체가 객체 자기 스스로가 아닌 어떠한 함수가 해준다면 어떻게 될까요??

정말 능력 있는 개발자가 관리한다면 빈틈없이 진행하겠죠 

하지만 사람은 언제든지 실수하기 마련입니다.

자신이 메모리를 할당하고서도 해제하는 것을 잊어버릴 수도 있다는 것이죠.

또 다른 경우로는 예외처리로 인해 메모리가 해제 되는 구문이 실행되지 않았다면??

절망의 나락으로 빠지는 건 한순간입니다. 그렇기 때문에 객체의 소멸자에서 메모리를 해제하는 구문을 넣어주는게

가장 안전한 방법이라고 할 수 있습니다.

이 내용을 정리하자면

첫째, 자원을 획득한 후에 자원 관리 객체에게 넘깁니다. 

쉽게 말해 메모리를 할당한 후 소유권을 객체에게 떠넘기는 것입니다.

간단한 예제로 Point *p = new Point(0, 0); 이라 할 수 있죠

필자는 "자원 획득 즉 초기화" 라는 용어를 통해 기본 값을 넣어주어야 한다고 써져 있는데

C++에서는 객체 및 변수를 선언 및 초기화를 해야하는 것이 보편적이니 이 부분은 넘어가겠습니다.

둘째, 자원 관리 객체는 자신의 소멸자를 사용해서 자원이 확실히 해제되도록 합니다.

소멸자는 객체가 소멸할 때 자동으로 호출하므로 소멸자에 자원 해제에 대한 코드를 넣는다면 반드시 해제가 됩니다.

이와 관련해서 나온 표준 라이브러리에 있는 대표적인 클래스로 auto_ptr와 참조 카운터 방식인 shared_ptr 있습니다. 

각각 클래스들은 자동으로 메모리를 관리함으로써 사용자가 메모리를 좀 더 쉽게 관리하는 기능을 제공합니다.

하지만 이 클래스들이 명시하는 delete는 일반 delete 이므로 배열에 관련된 메모리를 처리가 불가능합니다.

 

이것만은 잊지 말자!

* 자원 누출을 막기 위해, 생성자 안에서 자원을 획득하고 소멸자에서 그것을 해제하는 RAll 객체를 사용합시다.

* 일반적으로 널리 쓰이는 RAll 클래스는 tr1::shared_ptr 그리고 auto_ptr 입니다. 이 둘 가운데 tr1::shared_ptr이

복사 시의 동작이 직관적이기 때문에 대개 더 좋습니다.

반면, auto_ptr은 복사되는 객체(원본 객체)를 null로 만들어 버립니다.

 

 

 

Comments