템플릿은 C++을 강력한 언어로 만들어주는 기법 중의 하나입니다.
템플릿이라는 문법을 통해서 편리하게 STL을 사용할 수도 있습니다.
이 중에 auto_ptr이라는 스마트 포인터가 있습니다.
auto_ptr은 <memory>에 구현되어 있습니다.
제목에서 보이듯이 이 스마트 포인터는 반만 스마트합니다.
그 이유를 차근차근 보도록 하겠습니다.
auto_ptr은 템플릿 클래스로 만들어져 있기 때문에,
어떤 타입의 포인터든 받을 수 있습니다.
클래스의 특징 중 하나는 Scope(유효 범위)를 벗어나면 소멸자가 호출된다는 것인데
이 특징을 이용하고 있습니다.
만약 다음과 같은 코드가 있다면 메모리의 누수가 생깁니다.
void main()
{
int* pInt = new int;
*pInt = 10;
cout<<*pInt<<endl;
// delete pInt;
}
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
new로 동적할당을 하고 delete를 호출하지 않아서 메모리 누수가 있습니다.
void main()
{
auto_ptr<int> pInt(new int);
*pInt = 10;
cout<<*pInt<<endl;
}
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
이렇게 auto_ptr을 사용 가능합니다.
<> 안에 사용할 타입을 넣어주시면 됩니다.
auto_ptr은 구현을 보시면 소멸자(~auto_ptr())에 다음과 같이 되어 있습니다.
~auto_ptr()
{
delete _Myptr;
}
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
_Myptr은 auto_ptr이 내부적으로 관리하는 포인터입니다.
생성자가 동적할당된 주소를 받게 되어 있는데, 그 주소를 가리키는 포인터입니다.
Visual Studio에서는 _Ty *_Myptr; 으로 되어 있습니다.
템플릿에서 흔히 쓰는 표현으로는 T* _Myptr이 됩니다.
넘겨받은 주소를 저장하고 갖고 있다가 소멸자가 호출될 때,
delete _Myptr; 을 호출하는 것 뿐입니다.
여기서 auto_ptr의 한 가지 단점이 나옵니다.
동적할당을 배열 단위로 하면 정상적으로 메모리 해제가 안된다.
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
new int [5];로 할당하면 delete[] _Myptr로 바뀌어야 하는데
이미 소멸자의 코드는 delete _Myptr;로 고정되어 있습니다.
이 경우에는 메모리의 누수를 가져올 수 있습니다.
그리고 malloc()으로 할당된 메모리에 대해서도 정상적으로 해제가 안될 수 있습니다.
같은 이유로 malloc()은 free()와 쌍을 이뤄야 하기 때문입니다.
이러한 문제를 다른 스마트 포인터는 functor(함수 객체)라는
문법을 사용하여, 회피하고 있습니다.
소멸자에서 호출할 메모리 해제 코드를 직접 지정할 수 있습니다.
그리고 대입 등으로 내부의 포인터를 복사하면 복사가 되는 것이 아니라
이전의 auto_ptr은 NULL로 무효화처리 됩니다.
a = b;
위와 같을 때 일반적으로는 a와 b값이 같아지지만,
auto_ptr은 a에 b의 값이 들어가면서 b는 NULL로 바뀌어버립니다.
이렇게 되는 이유는 만약 a와 b가 같은 위치를 가리키고 있을 때, a가 먼저 delete로
해당 메모리 영역을 해제해버리면 b는 이미 해제된 영역을 다시 delete하기 때문에
문제가 생기기 때문입니다.
여기서 auto_ptr의 두 번째 단점이 나옵니다.
한 곳의 위치를 가리키는 2개의 auto_ptr을 생성할 수 없다.
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
억지로 가리킬 수는 있어도 나중에 해제 시에 반드시 문제가 생기게 됩니다.
auto_ptr에 release()라는 메소드가 존재하는데
자기가 갖고 있는 포인터를 반납(리턴)하면서 포인터를 NULL로 바꿉니다.
그래서 release()를 사용하면, 포인터를 돌려받고, auto_ptr 객체가 무효화 됩니다.
그래서 스마트 포인터들은 이 문제를 참조 카운트(Reference Count)를 통해서
해결합니다.
참조 카운트를 유지하면서 대입을 하거나 했을 때, 카운트를 하나씩 올려주고
소멸자가 호출되면, 카운트를 다시 하나씩 내려줍니다.
그러다가 마지막에 카운트가 0이 되는 순간 메모리를 해제하는 방법입니다.
shared_ptr이 이런 스마트 포인터 중 하나이며
COM에도 이런 기능을 하는 스마트 포인터들이 존재합니다.(CComPtr 등등...)
또, C++11에서는 auto_ptr에 Deprecated 되었다고 나옵니다.
앞으로를 위해서는 auto_ptr은 절대 사용하면 안됩니다.
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
unique_ptr은 auto_ptr을 대체합니다.
그 외에도 대체할 수 있는 스마트 포인터가 많이 있으므로 다른 스마트 포인터를
사용하시면 됩니다.
[출처] 반만 스마트한 포인터 auto_ptr|작성자 IT술사
'Basic Programming > C, C++' 카테고리의 다른 글
C++ - volatile 과 register 키워드 (0) | 2016.03.03 |
---|---|
C++ - 타입 캐스팅(static_cast, reinterpret_cast, dynamic_cast, const_cast) (0) | 2016.03.03 |
C++ - Explict와 Mutable 키워드 (0) | 2016.02.24 |
C++ - 함수 오버라이딩, 가상함수, 다형성 (0) | 2016.02.24 |
C++ - Visual C++에서 동적 메모리 체크하기 (0) | 2016.02.24 |