使用C ++ 17,shared_ptr
可用于管理动态分配的数组。shared_ptr
在这种情况下,模板参数必须为T[N]
或T[]
。所以你可以写
shared_ptr<int[]> sp(new int[10]);
从n4659开始,[util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
要求: Y
应为完整类型。表达式delete[] p
when T
为数组类型,或者delete p
when T
为非数组类型,应具有明确定义的行为,并且不得引发异常。
...
备注:当T
是数组类型时,该构造函数不得参与重载解析,除非该表达式delete[] p
格式正确,并且T
是U[N]
和Y(*)[N]
可以转换为T*
,或者T
是
U[]
和Y(*)[]
可以转换为T*
。...
为了支持这一点,element_type
现在将成员类型定义为
using element_type = remove_extent_t<T>;
数组元素可以使用 operator[]
element_type& operator[](ptrdiff_t i) const;
要求: get() != 0 && i >= 0
。如果T
是U[N]
,i < N
。...
备注:当T
不是数组类型时,不确定是否声明此成员函数。如果声明了它,则不明确其返回类型是什么,除了函数的声明(尽管不一定是定义)必须格式正确。
之前C ++ 17,shared_ptr
可以不被用来管理动态分配数组。默认情况下,当不再有对它的引用时,shared_ptr
将调用delete
该对象。但是,当您使用进行分配时,new[]
您需要调用delete[]
而不是delete
来释放资源。
为了正确使用shared_ptr
数组,必须提供自定义删除器。
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
如下创建shared_ptr:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
现在在销毁托管对象时shared_ptr
将正确调用delete[]
。
上面的自定义删除器可以替换为
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; });
另外,除非您确实需要共享托管对象的所有权,否则a unique_ptr
更适合于此任务,因为它对数组类型有部分专长。
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
C ++图书馆基础知识扩展引入的更改
库基础技术规范提供了上述C ++ 17之前版本的另一种替代方法,该标准经过扩充shared_ptr
后可以在拥有对象数组的情况下即开即用。shared_ptr
可以在N4082中找到有关此TS 的更改的当前草案。这些更改将通过std::experimental
名称空间进行访问,并包含在<experimental/memory>
标头中。支持shared_ptr
数组的一些相关更改包括:
—成员类型的定义element_type
更改
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
— operator[]
正在添加成员
element_type& operator[](ptrdiff_t i) const noexcept;
—与unique_ptr
数组的部分专业化不同,两者shared_ptr<T[]>
和shared_ptr<T[N]>
都将是有效的,并且两者都将导致在delete[]
对象的托管数组上被调用。
template<class Y> explicit shared_ptr(Y* p);
要求:Y
应为完整类型。表达式delete[] p
when T
为数组类型,或者delete p
when T
为非数组类型,格式应正确,行为应明确,并且不得引发异常。如果T
是U[N]
,Y(*)[N]
应转换为T*
; 当T
是U[]
,Y(*)[]
应转变成T*
; 否则,Y*
应转换为T*
。
std::vector
。您必须小心使用引用传递数组,以免复制它。访问数据的语法比shared_ptr干净,并且调整其大小非常简单。如果需要,您将获得所有STL优点。