C++ shared_ptr 到数组:应该使用它吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13061979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
shared_ptr to an array : should it be used?
提问by tshah06
Just a small query regarding shared_ptr
.
只是一个关于shared_ptr
.
Is it a good practice to use shared_ptr
pointing to an array? For example,
使用shared_ptr
指向数组是一个好习惯吗?例如,
shared_ptr<int> sp(new int[10]);
If not, then why not? One reason I am already aware of is one can not increment/decrement the shared_ptr
. Hence it can not be used like a normal pointer to an array.
如果没有,那为什么不呢?我已经知道的一个原因是不能增加/减少shared_ptr
. 因此它不能像普通的数组指针一样使用。
回答by Praetorian
With C++17, shared_ptr
can be used to manage a dynamically allocated array. The shared_ptr
template argument in this case must be T[N]
or T[]
. So you may write
使用C++17,shared_ptr
可用于管理动态分配的数组。shared_ptr
这种情况下的模板参数必须是T[N]
or T[]
。所以你可以写
shared_ptr<int[]> sp(new int[10]);
From n4659, [util.smartptr.shared.const]
从 n4659,[util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
shall be a complete type. The expressiondelete[] p
, whenT
is an array type, ordelete p
, whenT
is not an array type, shall have well-defined behavior, and shall not throw exceptions.
...
Remarks:WhenT
is an array type, this constructor shall not participate in overload resolution unless the expressiondelete[] p
is well-formed and eitherT
isU[N]
andY(*)[N]
is convertible toT*
, orT
isU[]
andY(*)[]
is convertible toT*
. ...
template<class Y> explicit shared_ptr(Y* p);
要求:
Y
应该是一个完整的类型。表达式delete[] p
,whenT
是数组类型,或者delete p
,whenT
不是数组类型,应具有明确定义的行为,并且不应引发异常。
...
备注:当T
是一个数组类型,则此构造不得参加重载除非表达delete[] p
是公形成,要么T
是U[N]
与Y(*)[N]
可转化为T*
或者T
是U[]
和Y(*)[]
可转化成T*
。...
To support this, the member type element_type
is now defined as
为了支持这一点,成员类型element_type
现在定义为
using element_type = remove_extent_t<T>;
Array elements can be access using operator[]
数组元素可以使用访问 operator[]
element_type& operator[](ptrdiff_t i) const;
Requires:
get() != 0 && i >= 0
. IfT
isU[N]
,i < N
. ...
Remarks:WhenT
is not an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
element_type& operator[](ptrdiff_t i) const;
要求:
get() != 0 && i >= 0
。如果T
是U[N]
,i < N
。...
备注:当T
不是数组类型时,未指定是否声明该成员函数。如果已声明,则未指定其返回类型是什么,除非函数的声明(尽管不一定是定义)格式正确。
Prior to C++17, shared_ptr
could notbe used to manage dynamically allocated arrays. By default, shared_ptr
will call delete
on the managed object when no more references remain to it. However, when you allocate using new[]
you need to call delete[]
, and not delete
, to free the resource.
之前C ++ 17,shared_ptr
可以不被用来管理动态分配数组。默认情况下,shared_ptr
将delete
在没有更多引用时调用托管对象。但是,当您分配 using 时,new[]
您需要调用delete[]
而非delete
来释放资源。
In order to correctly use shared_ptr
with an array, you must supply a custom deleter.
为了正确使用shared_ptr
数组,您必须提供自定义删除器。
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Create the shared_ptr as follows:
创建 shared_ptr 如下:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Now shared_ptr
will correctly call delete[]
when destroying the managed object.
现在shared_ptr
将delete[]
在销毁托管对象时正确调用。
The custom deleter above may be replaced by
上面的自定义删除器可以替换为
the
std::default_delete
partial specialization for array typesstd::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
a lambda expression
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
std::default_delete
数组类型的部分特化std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
一个 lambda 表达式
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Also, unless you actually need share onwership of the managed object, a unique_ptr
is better suited for this task, since it has a partial specialization for array types.
此外,除非您确实需要共享托管对象,否则 aunique_ptr
更适合此任务,因为它对数组类型具有部分专业化。
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Changes introduced by the C++ Extensions for Library Fundamentals
库基础的 C++ 扩展引入的更改
Another pre-C++17 alternative to the ones listed above was provided by the Library Fundamentals Technical Specification, which augmented shared_ptr
to allow it to work out of the box for the cases when it owns an array of objects. The current draft of the shared_ptr
changes slated for this TS can be found in N4082. These changes will be accessible via the std::experimental
namespace, and included in the <experimental/memory>
header. A few of the relevant changes to support shared_ptr
for arrays are:
另一个 C++17 之前的替代方案是由Library Fundamentals Technical Specification 提供的,它增加shared_ptr
了允许它在拥有一组对象的情况下开箱即用。shared_ptr
可以在N4082 中找到为此 TS 计划的更改的当前草案。这些更改可通过std::experimental
命名空间访问,并包含在<experimental/memory>
标题中。支持shared_ptr
数组的一些相关更改是:
— The definition of the member type element_type
changes
— 成员类型的定义element_type
发生变化
typedef T element_type;typedef typename remove_extent<T>::type element_type;
typedef T element_type;typedef typename remove_extent<T>::type element_type;
— Member operator[]
is being added
—operator[]
正在添加成员
element_type& operator[](ptrdiff_t i) const noexcept;
element_type& operator[](ptrdiff_t i) const noexcept;
— Unlike the unique_ptr
partial specialization for arrays, both shared_ptr<T[]>
and shared_ptr<T[N]>
will be valid and both will result in delete[]
being called on the managed array of objects.
— 与unique_ptr
数组的部分特化不同,shared_ptr<T[]>
和shared_ptr<T[N]>
都是有效的,并且都将导致在delete[]
对象的托管数组上被调用。
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
shall be a complete type. The expressiondelete[] p
, whenT
is an array type, ordelete p
, whenT
is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. WhenT
isU[N]
,Y(*)[N]
shall be convertible toT*
; whenT
isU[]
,Y(*)[]
shall be convertible toT*
; otherwise,Y*
shall be convertible toT*
.
template<class Y> explicit shared_ptr(Y* p);
要求:
Y
应该是一个完整的类型。表达式delete[] p
, whenT
是数组类型,或delete p
, whenT
不是数组类型,应格式良好,应具有明确定义的行为,并且不应引发异常。当T
是 时U[N]
,Y(*)[N]
应可转换为T*
; 当T
是 时U[]
,Y(*)[]
应可转换为T*
;否则,Y*
应转换为T*
。
回答by Timmmm
A possibly easier alternative that you might be able to use is shared_ptr<vector<int>>
.
您可以使用的一个可能更简单的替代方法是shared_ptr<vector<int>>
.