2014-09-04 5 views
-3

std::unique_ptr<int> upi{new int}을 수행 할 수 있으므로 즉시 std::unique_ptr<int*> upi{new int[42]{}}이 작동하지 않는 이유에 대해 혼란스러워졌습니다. 누군가가 다음 발췌 문장의 차이점을 설명 할 수 있습니까?int, int * 및 int []와 std :: unique_ptr의 차이점

{ 
    std::unique_ptr<int> upi{new int[42]{}}; 
    upi.get()[0]; 
} 

// Doesn't work 
{ 
    std::unique_ptr<int> upi{new int[42]{}}; 
    upi[0]; 
} 

{ 
    std::unique_ptr<int[]> upi{new int[42]{}}; 
    upi.get()[0]; 
}  

{ 
    std::unique_ptr<int[]> upi{new int[42]{}}; 
    upi[0]; 
}  

// Doesn't work 
{ 
    std::unique_ptr<int*> upi{new int[42]{}}; 
    upi.get()[0]; 
}  

// Doesn't work  
{ 
    std::unique_ptr<int*> upi{new int[42]{}}; 
    upi[0]; 
} 

컴파일러 오류 :

첫 번째 템플릿 매개 변수 (즉, int[] 대신 int의) 배열 유형을 지정 unique_ptr의 배열 버전을, 당신이 사용하기 위해
prog.cpp: In function ‘int main()’: 
prog.cpp:8:20: warning: value computed is not used [-Wunused-value] 
     upi.get()[0]; 
        ^
prog.cpp:14:12: error: no match for ‘operator[]’ (operand types are ‘std::unique_ptr<int>’ and ‘int’) 
     upi[0]; 
      ^
prog.cpp:19:20: warning: value computed is not used [-Wunused-value] 
     upi.get()[0]; 
        ^
prog.cpp:29:48: error: no matching function for call to ‘std::unique_ptr<int*>::unique_ptr(<brace-enclosed initializer list>)’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
prog.cpp:29:48: note: candidates are: 
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:176:2: note: template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&) 
    unique_ptr(auto_ptr<_Up>&& __u) noexcept; 
^
/usr/include/c++/4.8/bits/unique_ptr.h:176:2: note: template argument deduction/substitution failed: 
prog.cpp:29:48: note: mismatched types ‘std::auto_ptr<_Up>’ and ‘int*’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:169:2: note: template<class _Up, class _Ep, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Up, _Ep>&&) 
    unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept 
^
/usr/include/c++/4.8/bits/unique_ptr.h:169:2: note: template argument deduction/substitution failed: 
prog.cpp:29:48: note: mismatched types ‘std::unique_ptr<_Tp, _Dp>’ and ‘int*’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:160:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int*; _Dp = std::default_delete<int*>] 
     unique_ptr(unique_ptr&& __u) noexcept 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:160:7: note: no known conversion for argument 1 from ‘int*’ to ‘std::unique_ptr<int*>&&’ 
/usr/include/c++/4.8/bits/unique_ptr.h:157:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int*; _Dp = std::default_delete<int*>; std::nullptr_t = std::nullptr_t] 
     constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } 
       ^
/usr/include/c++/4.8/bits/unique_ptr.h:157:17: note: no known conversion for argument 1 from ‘int*’ to ‘std::nullptr_t’ 
/usr/include/c++/4.8/bits/unique_ptr.h:151:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**; typename std::remove_reference<_To>::type = std::default_delete<int*>] 
     unique_ptr(pointer __p, 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:151:7: note: candidate expects 2 arguments, 1 provided 
/usr/include/c++/4.8/bits/unique_ptr.h:146:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int*>&] 
     unique_ptr(pointer __p, 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:146:7: note: candidate expects 2 arguments, 1 provided 
/usr/include/c++/4.8/bits/unique_ptr.h:141:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**] 
     unique_ptr(pointer __p) noexcept 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:141:7: note: no known conversion for argument 1 from ‘int*’ to ‘std::unique_ptr<int*>::pointer {aka int**}’ 
/usr/include/c++/4.8/bits/unique_ptr.h:135:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int*; _Dp = std::default_delete<int*>] 
     constexpr unique_ptr() noexcept 
       ^
/usr/include/c++/4.8/bits/unique_ptr.h:135:17: note: candidate expects 0 arguments, 1 provided 
prog.cpp:30:20: warning: value computed is not used [-Wunused-value] 
     upi.get()[0]; 
        ^
prog.cpp:35:48: error: no matching function for call to ‘std::unique_ptr<int*>::unique_ptr(<brace-enclosed initializer list>)’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
prog.cpp:35:48: note: candidates are: 
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:176:2: note: template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&) 
    unique_ptr(auto_ptr<_Up>&& __u) noexcept; 
^
/usr/include/c++/4.8/bits/unique_ptr.h:176:2: note: template argument deduction/substitution failed: 
prog.cpp:35:48: note: mismatched types ‘std::auto_ptr<_Up>’ and ‘int*’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:169:2: note: template<class _Up, class _Ep, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Up, _Ep>&&) 
    unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept 
^
/usr/include/c++/4.8/bits/unique_ptr.h:169:2: note: template argument deduction/substitution failed: 
prog.cpp:35:48: note: mismatched types ‘std::unique_ptr<_Tp, _Dp>’ and ‘int*’ 
     std::unique_ptr<int*> upi{new int[42]{}}; 
               ^
In file included from /usr/include/c++/4.8/memory:81:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:160:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int*; _Dp = std::default_delete<int*>] 
     unique_ptr(unique_ptr&& __u) noexcept 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:160:7: note: no known conversion for argument 1 from ‘int*’ to ‘std::unique_ptr<int*>&&’ 
/usr/include/c++/4.8/bits/unique_ptr.h:157:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int*; _Dp = std::default_delete<int*>; std::nullptr_t = std::nullptr_t] 
     constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } 
       ^
/usr/include/c++/4.8/bits/unique_ptr.h:157:17: note: no known conversion for argument 1 from ‘int*’ to ‘std::nullptr_t’ 
/usr/include/c++/4.8/bits/unique_ptr.h:151:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**; typename std::remove_reference<_To>::type = std::default_delete<int*>] 
     unique_ptr(pointer __p, 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:151:7: note: candidate expects 2 arguments, 1 provided 
/usr/include/c++/4.8/bits/unique_ptr.h:146:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int*>&] 
     unique_ptr(pointer __p, 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:146:7: note: candidate expects 2 arguments, 1 provided 
/usr/include/c++/4.8/bits/unique_ptr.h:141:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int*; _Dp = std::default_delete<int*>; std::unique_ptr<_Tp, _Dp>::pointer = int**] 
     unique_ptr(pointer __p) noexcept 
    ^
/usr/include/c++/4.8/bits/unique_ptr.h:141:7: note: no known conversion for argument 1 from ‘int*’ to ‘std::unique_ptr<int*>::pointer {aka int**}’ 
/usr/include/c++/4.8/bits/unique_ptr.h:135:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int*; _Dp = std::default_delete<int*>] 
     constexpr unique_ptr() noexcept 
       ^
/usr/include/c++/4.8/bits/unique_ptr.h:135:17: note: candidate expects 0 arguments, 1 provided 
prog.cpp:36:12: error: no match for ‘operator[]’ (operand types are ‘std::unique_ptr<int*>’ and ‘int’) 
     upi[0]; 
      ^
+10

혹시 말하지 않을 시겠어요 사용해야합니다 다시 "작동하지 않는다"? –

+0

'int'는'int *'가 아닙니다. 당신이 가지고있는 것은 편집하지 않고, 훨씬 덜 "일"합니다. – WhozCraig

+0

즉 컴파일러 오류가 발생합니다. – user4009226

답변

6

에는 정의되지 않은 동작이 있습니다. new[]을 사용하여 메모리를 할당하고 unique_ptr은 소멸자에 이 아니라 delete을 호출하려고합니다. unique_ptr::operator[] 과부하 만 unique_ptr<T[]> 부분 특수화를 위해 존재하기 때문에

upi[0]; 

는 컴파일되지 않습니다. unique_ptr 생성자가 int**을 기대하고 있기 때문에

std::unique_ptr<int*> upi{new int[42]{}}; 

는 컴파일되지 않습니다,하지만 당신은 그에게 int*을 전달하고 있습니다. 만약 컴파일했다면, 이전의 경우와 같은 이유로 인해 정의되지 않은 동작을했을 것입니다.


당신은

std::unique_ptr<int[]> upi{new int[42]{}}; 
upi.get()[0] = 0; // this works 
upi[0] = 0;  // and so does this 
0

, 그렇지 않으면 당신을 대신 포인터 버전을 사용하고 있습니다.

int[]int*으로 분해 될 수 있습니다. 이 입력으로 int*을 소요하기 때문에 당신은 unique_ptr<int>의 생성자에 new int[]를 전달할 수 있지만, 대신 unique_ptr<int[]>을 사용하는 경우에만이, unique_ptr의 해당 버전에 존재하지 않기 때문에 당신은 upi[] 연산자를 액세스 할 수 없습니다.

+0

포인터 버전의 전문화는 어떻게 작성합니까? – user4009226

+0

'std :: unique_ptr '을 사용하고 싶다면'std :: unique_ptr upi {new int * [42] {}};와 같이 생성자에'int **'를 제공해야합니다. 물론'delete []'가 사용되지 않기 때문에 잘못되었습니다. 대신에'std :: unique_ptr upi {new int [42] {}};를 사용해야 할 것입니다. –

+0

'std :: unique_ptr' – user4009226

관련 문제