shared_ptr<T[]>包装动态数组时出现问题

Problems with shared_ptr<T[]> wrapping a dynamic array

本文关键字:数组 动态 问题 包装 ptr lt shared gt      更新时间:2023-10-16

我想用std::shared_ptr替换类中的一些原始指针,这样在创建该类的副本时就不必担心了。但是原始指针指向一个动态数组。当您为shared_ptr提供一个自定义的deleter时,可以将其与动态数组一起使用;g.CCD_ 2。

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

这里有一个最小的代码示例:

#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;
}

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


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

C: \Program Files(x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(754):错误C2664:"std::_Ptr_base&lt_Ty>::_Reset0":无法将参数1从"char"转换为"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>::_Resetp0&lt_Ux>(_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>::_Resetp0&lt_Ux>(_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>::_Resetp&lt_Ux,_Dx>(_Ux*,_Dx)'正在编译

[
_Ty=char[],
_Ux=字符,
_Dx=std::default_delete
]
C: \Program Files(x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\memory(494):请参阅对函数模板实例化的引用'void std::shared_ptr&lt_Ty>::_Resetp&lt_Ux,_Dx>(_Ux*,_Dx)'正在编译

[
_Ty=char[],
_Ux=字符,
_Dx=std::default_delete
]
problem.cpp(9):请参阅对函数模板实例化的引用"std::shared_ptr&lt_Ty>::shared_ptr>(_Ux*,_Dx)'正在编译

[
_Ty=char[],
T=字符,
_Ux=字符,
_Dx=std::default_delete
]
problem.cpp(9):请参阅对函数模板实例化的引用"std::shared_ptr&lt_Ty>::shared_ptr>(_Ux*,_Dx)'正在编译

[
_Ty=char[],
T=字符,
_Ux=字符,
_Dx=std::default_delete
]
problem.cpp(21):请参阅对函数模板实例化的引用"std::shared_ptr&lt_Ty>make_shared_array(size_t)'正在编译

[
_Ty=char[]
]

您建议的解决方案是可能的,但您将失去数组的大小:

#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;
}

我在这里所做的是让数组衰减为一个指针。只要deleter是数组deleter,它的行为就应该正确。

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

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

shared_ptr不是为处理数组而设计的。既然shared_array可用,为什么要尝试在数组上使用shared_ptr

如果指定了deleter,则在模板参数中不使用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;
};

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

您提到知道std::vector应该是一个更好的解决方案,但性能不太好。它应该表现得很好,你最好弄清楚为什么它没有。