With C++17, shared_ptr
可用于管理动态分配的数组。这shared_ptr
在这种情况下,模板参数必须是T[N]
or T[]
。所以你可以写
shared_ptr<int[]> sp(new int[10]);
从n4659开始,[util.smartptr.shared.const] https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared.const
template<class Y> explicit shared_ptr(Y* p);
要求: Y
应该是一个完整的类型。表达方式delete[] p
, when T
是数组类型,或者delete p
, when T
不是数组类型,应具有明确定义的行为,并且不应引发异常。
...
Remarks: When T
是数组类型,此构造函数不应参与重载决策,除非表达式delete[] p
是格式良好的,并且T
is U[N]
and Y(*)[N]
可转换为T*
, or T
is
U[]
and Y(*)[]
可转换为T*
. ...
为了支持这一点,成员类型element_type https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared#1现在定义为
using element_type = remove_extent_t<T>;
可以使用以下方式访问数组元素operator[] https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared.obs#8
element_type& operator[](ptrdiff_t i) const;
要求: get() != 0 && i >= 0
. If T
is U[N]
, i < N
.
...
Remarks: When T
不是数组类型,未指定是否声明该成员函数。如果声明了它,则未指定其返回类型是什么,但函数的声明(尽管不一定是定义)应格式良好。
C++17 之前, shared_ptr
could not用于管理动态分配的数组。默认情况下,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>());
Now shared_ptr
将正确调用delete[]
当销毁被管理对象时。
上面的自定义删除器可以替换为
-
the std::default_delete http://en.cppreference.com/w/cpp/memory/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; });
另外,除非您确实需要共享托管对象的所有权,否则unique_ptr
更适合此任务,因为它对数组类型有部分特化。
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
C++ 库基础扩展引入的更改
上面列出的另一种 C++17 之前的替代方案由库基础技术规范 http://en.cppreference.com/w/cpp/experimental/lib_extensions,这增强了shared_ptr
允许它在拥有对象数组的情况下开箱即用。目前的草案shared_ptr
可以在以下位置找到此 TS 的更改N4082 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4082.pdf。这些更改可通过std::experimental
命名空间,并包含在<experimental/memory>
标头。支持的一些相关更改shared_ptr
对于数组是:
— 成员类型的定义element_type
changes
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[]>
and shared_ptr<T[N]>
将是有效的,并且两者都会导致delete[]
在托管对象数组上调用。
template<class Y> explicit shared_ptr(Y* p);
Requires: Y
应该是一个完整的类型。表达方式delete[] p
, when T
是数组类型,或者delete p
, when T
不是数组类型,应格式良好,应具有明确定义的行为,并且不应引发异常。什么时候T
is U[N]
, Y(*)[N]
应可转换为T*
; when T
is U[]
, Y(*)[]
应可转换为T*
;否则,Y*
应可转换为T*
.