由于你可以std::unique_ptr<int> upi{new int}
,我立即对如何std::unique_ptr<int*> upi{new int[42]{}}
不起作用感到困惑。有人可以解释以下片段之间的区别吗?
{
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];
^
答案 0 :(得分:7)
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
答案 1 :(得分:0)
为了使用unique_ptr
的数组版本,您必须在第一个模板参数中指定数组类型(即int[]
而不是int
),否则您正在使用而是指针版本。
int[]
可以降级为int*
。您可以将new int[]
传递给unique_ptr<int>
的构造函数,因为它需要int*
作为输入,但是您无法访问upi[]
运算符,因为它在该版本中不存在unique_ptr
,仅在使用unique_ptr<int[]>
时。{/ p>