스토리텔링 개발자

[Effective STL] 8. auto_ptr 금지 본문

개발/Effective STL

[Effective STL] 8. auto_ptr 금지

김디트 2024. 11. 12. 10:33
728x90

항목 8. auto_ptr의 컨테이너는 절대로 만들지 말자

 

 

 

COAP(Container Of Auto Ptr) 금지
  • 사실 컴파일러가 통과도 시켜주지 않아야 정상이다.
  • 게다가 요새는 auto_ptr조차 표준이 아니다.
  • 하지만 이 책이 쓰여질 시기에는 이를 허용하는 컴파일러가 있었고, 그것이 문제였다.

 

 

 

COAP 금지 이유
  • 이식이 불가능하다.
    • 표준은 auto_ptr을 컨테이너에 담지 못한다, 이기 때문이다.
  • auto_ptr의 복사 동작이 문제된다.

 

 

 

auto_ptr의 복사 동작
  • 복사하면, 소유권이 옮겨지고, 기존의 것은 null로 셋팅된다.
  • 즉, auto_ptr을 복사하는 것은 '그 포인터의 값을 바꾸는 것이다'라고 할 수 있다.
auto_ptr<Widget> pw1(new Widget); // pw1 = 위젯의 포인터
auto_ptr<Widget> pw2(pw1); // pw1 = null, pw2 = 위젯의 포인터

pw1 = pw2; // pw1 = 위젯의 포인터, pw2 = null
  • 이 동작이 치명적일 때가 있다. 아래는 벡터의 예제.
bool widgetAPCompare(const auto_ptr<Widget>& lhs,
                     const auto_ptr<Widget>& rhs)
{
    return *lhs < *rhs;
}
vector< auto_ptr<Widget> > widgets;
...

sort(widgets.begin(), widgets.end(), widgetAPCompare); // 정렬 동작을 하면?
  • 정렬은 보통 퀵소트(quicksort) 알고리즘을 사용한다.
    • 컨테이너 내의 특정 요소를 "피벗 요소(pivot element)"로 선택한 후
    • 이 요소보다 큰 값과 작은 값의 집합을 구분하고
    • 두 집합에 대해 재귀 호출을 수행하여 정렬을 수행한다.
template<typename RandomAccessIterator, class Compare>
void sort(RndomAccessIterator first, RandomAccessIterator last, Compare comp)
{
    // RandomAccessIterator가 가리키는 객체의 타입
    // 위 벡터의 경우에는 auto_ptr<Widget> 이 될 것이다.
    typedef typename iterator_traits<RandomAccessIterator>::value_type ElementType;
    
    RandomAccessIterator i;
    ...
    ElementType pivotValue(*i); // 복사가 발생한다!!
    ...
}
  • 임시 변수로 복사되며 기존의 요소가 invalid 처리 된다는 의미이다.
728x90
Comments