2014-09-04 97 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]; 
} 

編譯器錯誤:

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

能否請你永遠不會再次說 「不工作」? – 2014-09-04 18:54:05

+0

'int'不是'int *'。你有什麼不*編譯*,更不用說「工作」。 – WhozCraig 2014-09-04 18:57:56

+0

這意味着我得到編譯器錯誤。s – user4009226 2014-09-04 18:58:08

回答

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

有未定義的行爲。您正在使用new[]分配內存,unique_ptr將在其析構函數中調用delete,而不是delete[]

upi[0]; 

不編譯,因爲過載unique_ptr::operator[]僅存在用於unique_ptr<T[]>偏特。

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

不編譯,因爲unique_ptr構造函數期待一個int**,但你傳遞一個int*。如果它編譯完成,由於與前一種情況相同的原因,它會有未定義的行爲。


您應該使用

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

爲了使用的unique_ptr數組版本,你必須指定用於第一個模板參數數組類型(即int[]代替int),否則你正在使用指針版本。

int[]可以降解爲int*。您可以將new int[]傳遞給unique_ptr<int>的構造函數,因爲它將int*作爲輸入,但不能訪問upi[]運算符,因爲它不存在於該版本的unique_ptr中,僅在使用unique_ptr<int[]>代替時才存在。

+0

如何爲指針版本編寫專門化? – user4009226 2014-09-04 19:04:40

+0

如果你想使用'std :: unique_ptr ',你必須爲構造函數提供一個'int **',比如'std :: unique_ptr upi {new int * [42] {}};'但是當然這是錯誤的,因爲'delete []'不會被使用。你將不得不使用'std :: unique_ptr upi {new int [42] {}};'而不是。 – 2014-09-04 19:07:22

+0

爲''upd [0]'工作'std :: unique_ptr ' – user4009226 2014-09-04 19:09:11

相關問題