shared_ptr <t []>包装动态数组的问题</t []>

时间:2013-02-19 12:20:53

标签: c++ c++11 shared-ptr

我想用std::shared_ptr替换我班级中的一些原始指针,以便在创建该类的副本时我不必担心。但原始指针指向动态数组。当您为其提供自定义删除器时,可以使用带动态数组的shared_ptr,例如: G。 default_delete<T[]>

但是,当我尝试为该字段分配新值时,即使在构建时,我也会得到一个大错误列表。

这是一个最小的代码示例:

#include <memory>
#include <cstddef>

using namespace std;

template<typename T> shared_ptr<T[]> make_shared_array(size_t size)
{
  return shared_ptr<T[]>(new T[size], default_delete<T[]>());
}

struct Foo
{
  shared_ptr<char[]> field;
};

int main()
{
  Foo a;
  // This line produces the error.
  a.field = make_shared_array<char>(256);

  return 0;
}

NB:是的,我知道我可以/应该vector而不是动态数组。但他们的表现并不相同。我做了一些繁重的图像处理,数组保持像素。在低于VGA分辨率的情况下,处理时间从8秒增加到11秒。那是非常多的。


更新:当然我可以在这里提供错误。我只是不知道我是否应该用它弄乱问题描述。但这是:

  

C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ VC \ INCLUDE \ memory(754):错误C2664:'std :: _ Ptr_base&lt; _Ty&gt; :: _ Reset0':无法从'char <转换参数1 em>'to'char()[]'
          与
          [
              _Ty = char []
          ]
          指向的类型是无关的;转换需要reinterpret_cast,C风格的演员或函数式演员           C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ VC \ INCLUDE \ memory(723):请参阅函数模板实例化'void std :: shared_ptr&lt; _Ty&gt; :: _ Resetp0&lt; _Ux&gt;(_ Ux *,std: :_Ref_count_base *)'正在编译中           与
          [
              _Ty = char [],
              _Ux =炭
          ]
          C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ VC \ INCLUDE \ memory(723):请参阅函数模板实例化'void std :: shared_ptr&lt; _Ty&gt; :: _ Resetp0&lt; _Ux&gt;(_ Ux *,std: :_Ref_count_base *)'正在编译中           与
          [
              _Ty = char [],
              _Ux =炭
          ]
          C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ VC \ INCLUDE \ memory(494):参见函数模板实例化'void std :: shared_ptr&lt; _Ty&gt; :: _ Resetp&lt; _Ux,_Dx&gt;(_ Ux *, _Dx)'正在编译中           与
          [
              _Ty = char [],
              _Ux =炭,
              _Dx =标准:: default_delete
          ]
          C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ VC \ INCLUDE \ memory(494):参见函数模板实例化'void std :: shared_ptr&lt; _Ty&gt; :: _ Resetp&lt; _Ux,_Dx&gt;(_ Ux *, _Dx)'正在编译中           与
          [
              _Ty = char [],
              _Ux =炭,
              _Dx =标准:: default_delete
          ]
          problem.cpp(9):参见函数模板实例化'std :: shared_ptr&lt; _Ty&gt; :: shared_ptr&gt;(_ Ux *,_ Dx)'正在编译的内容
          与
          [
              _Ty = char [],
              T =炭,
              _Ux =炭,
              _Dx =标准:: default_delete
          ]
          problem.cpp(9):参见函数模板实例化'std :: shared_ptr&lt; _Ty&gt; :: shared_ptr&gt;(_ Ux *,_ Dx)'正在编译的内容
          与
          [
              _Ty = char [],
              T =炭,
              _Ux =炭,
              _Dx =标准:: default_delete
          ]
          problem.cpp(21):参见函数模板实例化'std :: shared_ptr&lt; _Ty&gt; make_shared_array(size_t)'正在编译中           与
          [
              _Ty = char []
          ]

4 个答案:

答案 0 :(得分:8)

您建议的解决方案是可行的,但您将失去阵列的大小:

#include <memory>
#include <cstddef>

using namespace std;

template<typename T> shared_ptr<T> make_shared_array(size_t size)
{
   return shared_ptr<T>(new T[size], default_delete<T[]>());
}

struct Foo
{
  shared_ptr<char> field;
};

int main()  
{
  Foo a;
  a.field = make_shared_array<char>(256);

 return 0;
}

我在这里做的是让数组衰减成指针。只要删除器是数组删除器,它就应该正常运行。

为了防止这种大小的损失,如果你不能按照建议使用boost :: shared_array,我建议将这些信息封装在你自己的shared_array类中。

答案 1 :(得分:4)

如果您坚持不要使用std::vector,Boost会有一个boost::shared_array作为智能指针来管理动态分配的对象数组。

shared_ptr并非旨在处理数组。由于shared_array可用,为什么要尝试在数组上使用shared_ptr

答案 2 :(得分:3)

如果您指定了删除器,则不要在模板参数中使用T[]。只需将T[]更改为T

即可
template <typename T> shared_ptr<T> make_shared_array(size_t size)
{
  return shared_ptr<T>(new T[size], default_delete<T[]>());
}

struct Foo
{
  shared_ptr<char> field;
};

答案 3 :(得分:3)

std::unique_ptr专门用于数组类型,因此您可以使用T[],并且知道它仍然只存储T*std::shared_ptr不是以这种方式专门化的,因此shared_ptr<T[]>将尝试存储指向数组的指针T(*)[],这对于C ++中原始数组的约定不会很好。更不用说未知大小的数组是不完整的类型,shared_ptr最终将需要一个完整的类型。

你提到std::vector应该是一个更好的解决方案,但效果不佳。它应该表现得很好,你可能会更好地找出它为什么没有。