只是一个关于shared_ptr
.
shared_ptr
使用指向数组是一种好习惯吗?例如,
shared_ptr<int> sp(new int[10]);
如果不是,那为什么不呢?我已经知道的一个原因是不能增加/减少shared_ptr
. 因此它不能像普通的指向数组的指针一样使用。
只是一个关于shared_ptr
.
shared_ptr
使用指向数组是一种好习惯吗?例如,
shared_ptr<int> sp(new int[10]);
如果不是,那为什么不呢?我已经知道的一个原因是不能增加/减少shared_ptr
. 因此它不能像普通的指向数组的指针一样使用。
使用C++17,shared_ptr
可用于管理动态分配的数组。在这种情况下,shared_ptr
模板参数必须是T[N]
or T[]
。所以你可以写
shared_ptr<int[]> sp(new int[10]);
从 n4659,[util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
必须是一个完整的类型。表达式delete[] p
, whenT
是数组类型,或者delete p
, whenT
不是数组类型,应具有明确定义的行为,并且不应抛出异常。
...
备注:当T
是数组类型时,此构造函数不应参与重载决议,除非表达式delete[] p
是格式正确的并且要么T
isU[N]
并且Y(*)[N]
可转换为T*
,要么T
isU[]
并且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
管理动态分配的数组。默认情况下,当不再有对托管对象的引用时,将调用托管对象。但是,当您分配 using 时,您需要调用而不是调用来释放资源。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; });
此外,除非您确实需要托管对象的共享权限,否则 aunique_ptr
更适合此任务,因为它具有数组类型的部分特化。
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Library Fundamentals Technical Specification提供了上面列出的另一个 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);
Requires :
Y
应该是一个完整的类型。表达式delete[] p
, whenT
是一个数组类型,或者delete p
, whenT
不是一个数组类型,应该是格式良好的,应该有明确定义的行为,并且不应该抛出异常。T
什么时候U[N]
,Y(*)[N]
应转换为T*
; 什么时候,应转换T
为; 否则,应转换为.U[]
Y(*)[]
T*
Y*
T*
您可能可以使用的一个可能更简单的替代方法是shared_ptr<vector<int>>
.