C++ 阵列的共享ptr:是否应使用它?

C++ 阵列的共享ptr:是否应使用它?,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,只是一个小问题 使用shared_ptr指向数组是否是一种好的做法?比如说, shared_ptr<int> sp(new int[10]); shared_ptr sp(新整数[10]); 如果没有,为什么不呢?我已经知道的一个原因是不能增加/减少共享\u ptr。因此,它不能像指向数组的普通指针那样使用。使用C++17,共享\u ptr可用于管理动态分配的数组。在这种情况下,shared\u ptr模板参数必须是T[N]或T[]。所以你可以写 shared_ptr<in

只是一个小问题

使用
shared_ptr
指向数组是否是一种好的做法?比如说,

shared_ptr<int> sp(new int[10]);
shared_ptr sp(新整数[10]);

如果没有,为什么不呢?我已经知道的一个原因是不能增加/减少
共享\u ptr
。因此,它不能像指向数组的普通指针那样使用。

使用C++17
共享\u ptr
可用于管理动态分配的数组。在这种情况下,
shared\u ptr
模板参数必须是
T[N]
T[]
。所以你可以写

shared_ptr<int[]> sp(new int[10]);
可以使用

要求:
get()!=0&&i>=0
。如果
T
U[N]
i
。 …
备注:当
T
不是数组类型时,未指定是否声明此成员函数。如果已声明,则未指定其返回类型,除非函数的声明(尽管不一定是定义)格式良好


在C++17之前
shared_ptr
可以用于管理动态分配的阵列。默认情况下,
shared\u ptr
将在托管对象上调用
delete
,此时不再保留对该对象的引用。但是,当您使用
new[]
进行分配时,需要调用
delete[]
,而不是
delete
,以释放资源

为了正确地将
共享\u ptr
与数组一起使用,必须提供自定义删除程序

template< typename T >
struct array_deleter
{
  void operator ()( T const * p)
  { 
    delete[] p; 
  }
};
  • lambda表达式

    std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
    

    C++扩展对图书馆基础知识的影响 上述C++17之前版本的另一个替代方案是由提供的,它扩展了
    shared_ptr
    ,允许它在拥有一个对象数组的情况下开箱即用。此TS的
    共享\u ptr
    更改的当前草稿可在中找到。这些更改可以通过
    std::experimental
    名称空间访问,并包含在
    标题中。为支持阵列的
    shared_ptr
    而进行的一些相关更改包括:

    -成员类型
    元素类型
    的定义发生变化

    类型定义T元素_类型

    -与数组的
    unique_ptr
    部分专门化不同,
    shared_ptr
    shared_ptr
    都将有效,并且都将导致在对象的托管数组上调用
    delete[]

    模板显式共享ptr(Y*p);
    
    要求:
    Y
    应为完整类型。表达式
    delete[]p
    ,当
    T
    是数组类型时,或
    delete p
    ,当
    T
    不是数组类型时,应格式良好,行为定义明确,且不应引发异常。当
    T
    U[N]
    时,
    Y(*)[N]
    应可转换为
    T*
    ;当
    T
    U[]
    时,
    Y(*)[]
    应可转换为
    T*
    ;否则,
    Y*
    应可转换为
    T*


    您可以使用的一个可能更简单的替代方法是
    共享\u ptr

    +1,注意:还有Boost的。@tshah06返回一个指向托管对象的指针。因此,您可以将其用作sp.get()[0]=1。。。sp.get()[9]=10
    ALT:
    std::shared_ptr sp(新int[10],std::default_delete())也见@杰瑞米。如果编译时已知大小,则不必为此编写一个类,<代码> STD::SysDypPTR 应该足够了。为什么<代码> UnQuyPPTR <代码>获得部分专门化,但<代码> SydDypTR 不?FWITT,您也可以考虑只使用<代码> STD::vector < /代码>。您必须小心使用引用传递数组,以免复制它。访问数据的语法比shared_ptr更简洁,调整大小也非常容易。如果您想在编译时确定数组的大小,那么您也可以考虑使用<代码> STD::数组< /代码>。它几乎与原始数组相同,但在大多数库组件中使用适当的语义。尤其是使用
    delete
    而不是
    delete[]
    销毁该类型的对象。与向量不同的是,它将数据直接存储在对象中,因此不会得到额外的分配。是的。或者向量是数组的超集-它具有相同的内存表示(加上元数据),但可以调整大小。实际上,没有任何情况下需要数组但不能使用向量。这里的区别是向量大小不再是静态的,对数据的访问将通过双间接方式完成。如果性能不是关键问题,那么这是可行的,否则共享阵列可能有其自身的原因。然后您可能可以使用
    共享\u ptr
    。另一个区别是,它比原始阵列稍大、稍慢。一般来说,这不是一个真正的问题,但我们不要假设1==1.1。在某些情况下,数组中的数据源意味着转换为向量是不方便或不必要的;例如,从相机获取帧时。(或者,无论如何,这是我的理解)
      element_type& operator[](ptrdiff_t i) const;
    
    template< typename T >
    struct array_deleter
    {
      void operator ()( T const * p)
      { 
        delete[] p; 
      }
    };
    
    std::shared_ptr<int> sp(new int[10], array_deleter<int>());
    
    std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
    
    std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
    
    std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
    
     typedef typename remove_extent<T>::type element_type;
    
     element_type& operator[](ptrdiff_t i) const noexcept;
    
     template<class Y> explicit shared_ptr(Y* p);