오랜만에 강좌를 올립니다... ^^
Standard Library에서 제공하는 Smart pointer의 한 종류인
auto_ptr에 대한 사용법과 주의 할 점을 다루고자합니다.
여러가지 관점에서 smart pointer는 만들어지고 사용되고 있습니다.
Smart Pointer에 대한 내용은
http://en.wikipedia.org/wiki/Smart_pointer
http://www.boost.org/libs/smart_ptr/smart_ptr.htm 참고하세요.
auto_ptr은 단 한 가지 문제에 대해서만 효과가 있는 Smart pointer의 한 종류입니다.
그러므로 사용 방법을 정확히 알아야 합니다. 한 가지 문제라는 부분은 memory leak 방지를 위한
자동 소멸에 대한 부분입니다. 우선 일반적인 Pointer 예를 보고 auto_ptr에 대하여 살펴보도록 합시다.
예제 1.
void function() { AClass *p = new AClass; ... delete p; } |
흔히 예외에 대하여 생각하지 않는 예제를 만들거나 초보자가 하는 형태는 pointer를 선언하고
new를 이용하여 명시적으로 객체를 생성하고, delete를 이용하여 객체를 제거합니다.
그리고, 보다 심각한 경우가 p 를 return 할 경우 인데, 어떤 경우든
실행도중 예외가 발생하면 delete가 실행 되지 않아 memory leak이 발생하게 됩니다.
이를 방지하려면 모든 예외를 방지 해야하는데, 코드가 복잡해 지는 문제가 생깁니다.
예제 2.
void function() { AClass *p = new AClass; try{ ... } catch ( const std::exception& error ){ delete p; throw; } catch (...){ delete p; throw; } delete p; } |
이런 경우 필요한 것이 Smart Pointer인데 C++ Standard Library의 auto_ptr 를 살펴 보겠습니다.
예제 3.
#include <memory> void function() { std::auto_ptr<AClass> p( new AClass ); ... } |
더 이상 delete나 catch는 필요하지 않습니다. 예외를 일으켜도 문제 될 것이 없어집니다.
auto_ptr<> 은 -> 로 클래스나 구조체의 멤버를 이용하고 , * 로 역참조 할 수 있습니다.
하지만 = 을 이용해서 초기화 할 수 없습니다. 그러니까.
auto_ptr<AClass> p( new AClass ); 이런 형태로 초기화 하지만
auto_ptr<AClass> p = new AClass; 이것은 에러 입니다.
말그대로 명시적 선언으로만 초기화가 된다는 것입니다. ( 명시적 explicit, 묵시적 implicit 선언은 가장 아래.)
auto_ptr<> 사용에 주의할 점이 있습니다. 아래 사항은 반드시 숙지해 두고 사용하기 바랍니다.
1. 소유권 공유 할 수 없습니다. (auto_ptrs cannot share ownership.)
2. 배열 타입은 지원하지 않습니다. (auto_ptrs are not provided for arrays.)
3. 범용 스마트 포인터가 아닙니다. (auto_ptrs are not "universal smart pointers.")
4. STL container의 요소로 사용하면 안됩니다. (auto_ptrs don't meet the requirements for container elements.)
소유권 이전 부분을 좀 여러가지 관점에서 봐야하는데 우선 간단하게,
auto_ptr<AClass> p1 ( new AClass );
auto_ptr<AClass> p2 ( p1 );
이렇게 하면 p1은 NULL이 되고 p2는 p1이 가지고 있던 객체를 가지게 됩니다.
일반적인 포인터에서 p1과 p2는 같은 객체를 지정하게 됩니다. ( AClass *p1 = new AClass; AClass *p2; p2 = p1; )
이러한 것 여러가지 문제를 일으키게 됩니다.
auto_ptr의 좋은 예는 exceptional c++의 강경한 예외 안정성(strong exception safety)을 지킬 수 있는
code 예가 좋을 것 같습니다.
아래 code에서 예외가 발생할 수 있는 곳은 몇 군데 일까요....?
std::string EvaluateSalaryAndReturnName( Employee e ) { if( e.Title() == "CEO" || e.Salary() > 100000 ){ std::cout << e.First() << " " << e.Last() << " is overpaid" << endl; } return e.First() + " " + e.Last(); } |
23 곳입니다. 제가 찾은건 20개 였었는데, 내용을 보니 이해가 되더군요. 어쨌든 아래 예가 strong exception safety를
고려한 code 입니다.
std::auto_ptr<std::string> EvaluateSalaryAndReturnName( Employee e ) { std::auto_ptr<std::string> result = new std::string( e.First() + " " + e.Last() ); if( e.Title() == "CEO" || e.Salary() > 100000 ){ std::string message = (*result) + " is overpaid\n"; std::cout << message; } return result; } |
마지막으로 잊지 말아야 할 것은 소유권을 넘지지 않을 경우 그러니까 함수의 parameter나 argurment로
사용할 때 반드시 const로 하여야 합니다. 그러니까.
void function( const std::auto_ptr<ValueType> &p )
와 같이 const를 사용하여야 합니다. 그렇지 않으면 소유권이 넘어가 버리기 때문에 문제가 생기는건 당연한 것이죠.
오늘은 여기 까지 입니다. 설명이 부족한 부분은 덧글 질문해 주시기 바랍니다.
참고 explicit, implicit conversion
[
AClass a
BClass b(a) explicit conversion
AClass a;
BClass b = a; implicit conversion
]
'C C++ - STL' 카테고리의 다른 글
STL - 14 STL container map 응용 - Singleton pattern 적용한 Config 처리 (0) | 2014.02.13 |
---|---|
STL - 13 allocator (0) | 2014.02.13 |
STL - 11 Function Object (함수 - 객체) (0) | 2014.02.13 |
STL - 10 Vector Container 구현 (0) | 2014.02.13 |
STL - 9 find, find_if (0) | 2014.02.13 |