본문 바로가기

잡동사니(OLD)/프로그래밍 언어스킬

[VS2010 기술] unique_ptr 은? ( 01/02 )

이글은  MS VS2010 공식 팀 블로그에서 발췌한 내용입니다 

Remind

주요 변경 사항으로 소개되 내용에서, unique_ptr에 대해서 다음과 같이 설명하고 있습니다.

"auto_ptr 클래스보다 더 안전한 스마트 포인터형인 unique_ptr 클래스의 구현에도 Rvalue reference가 사용되었습니다. unique_ptr 클래스는 move는 할 수 있지만 copy는 불가능하며, safety에 영향을 미치지 않으면서 강한 소유 의미(strict ownership semantics)를 구현했습니다. 또한, unique_ptr 클래스는 rvalue references가 구현된 container들과 잘 동작합니다."

unique_ptr in MSDN Library

MSDN Library에 소개된 unique_ptr class에 관한 설명입니다.

- 소유하는 객체에 대한 포인터를 저장한다. 해당 객체는 다른
unique_ptr에 의해서 소유될 수 없다. 해당 객체는 unique_ptr이 해제될 때에 해제된다. 다음은 MSDN에 게시되어 있는 class 정의 코드입니다.

  1 template<class Type, class Del = default_delete<Type> >
  2     
class unique_ptr {
  3
  4
public:
  5         
typedef Type element_type;
  6         
typedef Del deleter_type;
  7         
typedef T1 pointer;
  8
  9         
unique_ptr ();
 10         
unique_ptr (
 11             
nullptr_t _Nptr
 12         
);
 13         
explicit unique_ptr (
 14             
pointer _Ptr
 15         
);
 16         
unique_ptr (
 17             
pointer _Ptr,
 18             
typename conditional<
 19                 
is_reference<Del>::value, 
 20                 
Del,
 21                 
typename add_reference<const Del>::type
 22             
>::type _Deleter
 23         
);
 24         
unique_ptr (
 25             
pointer _Ptr,
 26             
typename remove_reference<Del>::type&& _Deleter
 27         
);
 28         
unique_ptr (
 29             
unique_ptr&& _Right
 30         
);
 31         
template<class Type2, Class Del2>
 32             
unique_ptr (
 33                 
unique_ptr<Type2, Del2>&& _Right
 34             
);
 35
 36     
~unique_ptr ();
 37
 38     
unique_ptr& operator= (
 39         
unique_ptr&& _Right
 40     
);
 41     
template<class Type2, Class Del2>
 42         
unique_ptr& operator= (
 43             
unique_ptr<Type2, Del2>&& _Right
 44         
);
 45     
void swap (
 46         
unique_ptr& _Right
 47     
);
 48     
pointer release ();
 49     
void reset (
 50        
pointer _Ptr = pointer()
 51     
);
 52
 53     
pointer get () const;
 54     
Type& operator* () const;
 55     
pointer operator-> () const;
 56     
Del& get_deleter ();
 57     
const Del& get_deleter () const;
 58     
explicit operator bool () const;
 59
 60     
unique_ptr(
 61         
const unique_ptr& _Right
 62
) = delete;
 63     
unique_ptr& operator=(
 64         
const unique_ptr& _Right
 65
) = delete;
 66
 67
private:
 68     
pointer stored_ptr;    // exposition only
 69     
Del stored_deleter;    // exposition only
 70     
};



왜 auto_ptr은 deprecation이 되었을까?
  C++ 0x에서 auto_ptr은 deprecation으로 결정되었습니다. C++ 0x에서는 최소한 auto_ptr과 같은 효율을 가지며 move semantics를 지워하는 unique_ptr을 추가하게 됩니다. 그렇다면 auto_ptr은 왜 deprecation이 되었을까요? 그 이유에 대해서 설명드리겠습니다.

  역사적으로 이전 버전의 C++ 표준에서, 반복된 수정과 패치를 통해서 주요 확장에서 auto_ptr은 안정성을 확보했습니다. 하지만 설계상의 심각한 결함을 극복하지는 못했습니다. 대표적으로 generic 알고리즘과 auto_ptr을 함께 사용할 때에 문제가 되었습니다. generic 알고리즘에서는 복사 연산 문법은 정말로 copy 연산이 일어난다는 것을 가정합니다. 하지만 auto_ptr에서 복사 연산자는 실제로 move와 같이 동작합니다. 이런 근본적인 차이 때문에 알고리즘의 구현에 따라서 원하는 결과를 얻지 못 할 수도 있었습니다.

 정렬 알고리즘을 통해서 예를 들겠습니다. 버블 정렬이나 선택 정렬에서는 하나의 지역변수에 한 원소를 골라서 복사를 하는 방식을 사용합니다. 이런 경우에는 완벽하게 유효한 구현이 됩니다. 하지만 빠른 정렬의 경우를 생각해보면, 구현 중에 다음과 같은 코드가 있을 겁니다.

  value_type pivot = *mid_point;

 이 경우에 알고리즘상 복사 연산자에서 실제로 복사가 일어남을 전제하는 알고리즘인 겁니다. 하지만 auto_ptr은 복사 표현을 통해서 move를 구현했기 때문에 이런 구현에서는 sort()의 결과가 안전할 것인지 보장 할 수가 없었습니다.

 수년간의 논의 끝에, C++ 표준 위원회는 auto_ptr은 deprecated로 결정했습니다. 하지만 auto_ptr의 다른 모든 장점을 수용할 수 있으며 더 안전하고 명확한 인터페이스를 C++ 0x에 추가 될 필요가 있었고, 그 대채자가 unique_ptr 입니다. unique_ptr은 복사 생성자를 private으로 선언합니다. 따라서 generic 알고리즘을 unique_ptr과 같이 사용하여 호출할 때에, 모든 generic 코드는 컴파일 타임에 에러가 나거나 그렇지 않다면 완벽하게 유효한 결과를 내게 됩니다.

 다음 글에서는 unique_ptr의 예제 코드 위주로 auto_ptr과의 차이점과 개선점을 살펴보도록 하겠습니다.