먼저, 일반적인 코드를 보겠습니다.
AA라는 클래스를 동적할당하고 사용후에 해제를 해줍니다.
프로그래머가 동적으로 생성한 객체를 별도로 해제해주어야 하는데 C++ 에서는 new와 delete를 사용해서 일일이 입력해주어야 합니다.
물론 꼼꼼한 프로그래머라면 당연히 해제도 신경써야하지만, 만약에 신경을 쓰지 못하거나 애매한 상황이 와버리면 어떨까요?
아주 극단적인 코드를 작성해 보겠습니다.
비멤버함수인 Func에서 0~9까지의 난수를 생성해서 동적할당으로 생성된 test라는 클래스를 생성하고 그 값을 리턴하고 있습니다. 그럼 여기서 Func가 호출될때마다 생성되는 AA라는 객체를 어디서 해제해 줘야 할까요?
return 이전에 넣자니 값을 돌려주기전에 객체가 메모리에서 제거된 후에 쓰레기값을 리턴하게 되고, return문 이후에 넣자니 delete가 실행조차 되지 않습니다. 차라리 멤버함수라면 처리가 쉬울텐데 말이죠...
(물론 다른 함수를 이용한다거나 하는 방법도 있겠습니다만...)
불필요한 메모리도 자동으로 정리해주고 이런 난감한 상황에서(코드가 더 난감...) 사용할 수 있는 것이 스마트 포인터 입니다.
일단 스마트 포인터를 직접 만들어 보겠습니다.
별도의 delete 명령없이도 동적할당한 객체가 아주 잘 해제 됩니다.
하지만 우리가 원하는 비멤버 함수인 Func에 적용시에 정상적인 작동이 되지 않습니다.
Func 함수에서 리턴한 후에 자신이 소속된 함수가 끝나버렸기 때문에 고생해서 만든 자가 스마트 포인터가 자동으로 소멸자가 호출되기 때문입니다.
auto_ptr
그렇다고 상심하기에는 아직 이른것 같습니다.! 그럼 C++에서 제공되는 auto_ptr을 사용해보겠습니다.
생성한 객체가 별도의 delete 없이 자동으로 해제 됩니다.
이렇게만 본다면 만능인것 같습니다. 하지만 이런 auto_ptr에도 단점이 있습니다.
1. 배열을 사용할 수 없습니다.(boost::scoped_array , boost::shared_array 제외)
[일반적인 동적할당의 경우 배열을 사용할 수 있습니다. 하지만 auto_ptr은 사용할 수 없습니다.]
2. 복사시에 동작이 직관적이지 않습니다. (복사되는 객체(원본 객체)를 NULL로 만들어 버립니다.)
위에 auto_ptr보다 조금 더 개선된 shared_ptr가 있습니다.
shared_ptr
shared_ptr 객체의 복사나 대입이 발생하여 참조 shared_ptr 객체 수 증가하게 되고 나중에 대입이나 참조하고 있는 객체가 없다면, 해당 shared_ptr 가 자동으로 소멸되게 됩니다.
일반적으로 shared_ptr 가 복사 시의 동작이 직관적이기 때문에 대개 더 좋습니다.
단, 배열을 사용할 수 없다는 점은 auto_ptr와 같습니다.
스마트 포인터도 좋지만 적재 적소에 동적 할당한 객체를 열심히 해제해주는 습관을 들여야겠습니다.
나머지 부분에 대해서는 조금 더 공부하고 작성해야겠습니다.
(참고 : Effective C++)
'프로그래밍 > C++' 카테고리의 다른 글
[C/C++] 비트 연산과 시프트 연산 (0) | 2016.09.27 |
---|---|
[C++] 생성자와 소멸자 (0) | 2015.11.15 |
[ C++]연산자 오버로딩(1) - operator 키워드 (0) | 2015.10.20 |
[ C++]클래스 상속(4) - 순수 가상 함수 & 다중 상속 (0) | 2015.09.29 |
[ C++]클래스 상속(3) - 가상 함수 (0) | 2015.09.29 |