我想用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 []
]
答案 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
应该是一个更好的解决方案,但效果不佳。它应该表现得很好,你可能会更好地找出它为什么没有。