tsh*_*h06 157 c++ shared-ptr c++11
只是一个小问题shared_ptr.
使用shared_ptr指向数组是一个好习惯吗?例如,
shared_ptr<int> sp(new int[10]);
Run Code Online (Sandbox Code Playgroud)
如果没有,那么为什么不呢?我已经意识到的一个原因是不能增加/减少shared_ptr.因此,它不能像正常指向数组的指针一样使用.
Pra*_*ian 243
使用C++ 17,shared_ptr可用于管理动态分配的数组.shared_ptr在这种情况下,模板参数必须是T[N]或T[].所以你可以写
shared_ptr<int[]> sp(new int[10]);
Run Code Online (Sandbox Code Playgroud)
来自n4659,[util.smartptr.shared.const]
Run Code Online (Sandbox Code Playgroud)template<class Y> explicit shared_ptr(Y* p);要求:
Y应为完整类型.表达式delete[] p,当T是数组类型时,或者delete p,当T不是数组类型时,应具有明确定义的行为,并且不应抛出异常.
...
备注:当T是一个数组类型,则此构造不得参加重载除非表达delete[] p是公形成,要么T是U[N]与Y(*)[N]可转化为T*或者T是U[]和Y(*)[]可转化成T*....
为了支持这一点,成员类型element_type现在定义为
using element_type = remove_extent_t<T>;
Run Code Online (Sandbox Code Playgroud)
可以使用数组元素进行访问 operator[]
Run Code Online (Sandbox Code Playgroud)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;
}
};
Run Code Online (Sandbox Code Playgroud)
创建shared_ptr,如下所示:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Run Code Online (Sandbox Code Playgroud)
现在shared_ptr将delete[]在销毁托管对象时正确调用.
上面的自定义删除器可以替换为
std::default_delete数组类型的部分特化
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
Run Code Online (Sandbox Code Playgroud)一个lambda表达式
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Run Code Online (Sandbox Code Playgroud)此外,除非您确实需要共享托管对象的onwership,否则a unique_ptr更适合此任务,因为它具有数组类型的部分特化.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Run Code Online (Sandbox Code Playgroud)
图书馆基础技术规范提供了另一种前C++ 17替代方案,它扩展shared_ptr到允许它在拥有一系列对象的情况下开箱即用.目前shared_ptr该TS 的变更草案可在N4082中找到.这些更改将通过std::experimental命名空间访问,并包含在<experimental/memory>标头中.支持shared_ptr数组的一些相关更改是:
- 成员类型的定义element_type更改
typedef T element_type;Run Code Online (Sandbox Code Playgroud)typedef typename remove_extent<T>::type element_type;
- operator[]正在加入成员
Run Code Online (Sandbox Code Playgroud)element_type& operator[](ptrdiff_t i) const noexcept;
-不同于unique_ptr用于阵列部分特,都shared_ptr<T[]>和shared_ptr<T[N]>将是有效的,都将导致delete[]被称为对象的管理的阵列上.
Run Code Online (Sandbox Code Playgroud)template<class Y> explicit shared_ptr(Y* p);要求:
Y应为完整类型.表达式delete[] p,当T是数组类型时,或者delete p,当T不是数组类型时,应该是格式良好的,应该具有良好定义的行为,并且不应抛出异常.如果T是U[N],Y(*)[N]应转换为T*; 当T是U[],Y(*)[]应转变成T*; 否则,Y*应可转换为T*.
Tim*_*mmm 25
您可以使用的更容易的替代方案是shared_ptr<vector<int>>.