안녕하세요. 이번 글에서는 unique_ptr에 대해서 소개드리겠습니다.
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 };
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과의 차이점과 개선점을 살펴보도록 하겠습니다.
'C++0x' 카테고리의 다른 글
[STL] 4. make_shared (8) | 2010.08.12 |
---|---|
[STL] 3. unique_ptr (2/2) (0) | 2010.08.04 |
[STL] 1. What's new in VC++ 2010? (0) | 2010.06.07 |
[Plus C++0x] 람다(Lambda) 이야기 (마지막회) (2) | 2010.06.03 |
[Plus C++0x] 람다(Lambda) 이야기 (3) (0) | 2010.06.01 |