在related question中,我询问了如何创建通用容器。使用多态模板似乎是正确的方法。
但是,我不能为我的生活弄清楚应该如何编写析构函数。我希望分配的内存的所有者是容器,即使示例构造函数接收了T
的数组(及其维度),也在其他位置分配。
我希望能够做类似
的事情MyContainer<float> blah();
...
delete blah;
和
MyContainer<ComplexObjectType*> complexBlah();
...
delete complexBlah;`
我可以这样做吗?我可以在没有智能指针的情况下完成吗?
再次感谢您的意见。
答案 0 :(得分:4)
我建议您是否要存储指向复杂类型的指针,将容器用作MyContainer<shared_ptr<SomeComplexType> >
,对于基本类型,只需使用MyContainer<float>
。
shared_ptr
应该在被破坏时适当地删除复杂类型。当原始类型被破坏时,什么都不会发生。
如果以这种方式使用容器,则不需要太多的析构函数。你如何把你的物品放在容器里?您是否在堆上使用STL容器或数组? STL容器会自行删除。如果删除数组,这将导致每个元素的析构函数被执行,如果每个元素都是shared_ptr
,shared_ptr
析构函数将删除它自己持有的指针。
答案 1 :(得分:1)
你很可能做想在这里使用智能指针,它确实简化了问题。但是,就像一个练习一样,确定给定类型是否为指针很容易。粗略的实现(可能更优雅,但我不想介绍int2type):
typedef char YesType;
typedef char NoType[2];
template<typename T>
struct IsPointer
{
typedef NoType Result;
};
template<typename T>
struct IsPointer<T*>
{
typedef YesType Result;
};
template<typename T>
struct MyContainer
{
~MyContainer()
{
IsPointer<T>::Result r;
Clear(&r);
delete[] data;
}
void Clear(YesType*)
{
for (int i = 0; i < numElements; ++i)
delete data[i];
}
void Clear(NoType*) {}
T* data;
int numElements;
};
答案 2 :(得分:0)
可以做到,但这是非常先进的东西。 你需要使用类似boost MPL库(http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/index.html)的东西,这样你就可以让MyContainer的析构函数选择正确的破坏形式,它需要对容器上的各个项目进行破坏。您可以使用boost TypeTraits库来决定需要哪种删除(http://www.boost.org/doc/libs/1_36_0/libs/type_traits/doc/html/index.html)。我确信它会有一个特性让你决定你所包含的类型是否是一个指针,从而决定它是如何被破坏的。您可能需要自己为要在MyContainer中使用的具有任何其他特定删除要求的任何其他类型实现特征。祝你好运!如果你解决了,请告诉我们你是如何做到的。
答案 3 :(得分:0)
如果您不想使用智能指针,可以尝试部分模板特化,那么您可以编写一个模板,仅在使用指针类型实例化容器时使用。
答案 4 :(得分:0)
delete用于释放先前使用new
分配的内存。你不需要在这里使用delete,当blah和complexBlah超出范围时,它们将自动被销毁。
虽然yrp's answer向您展示了一种使用模板特化来删除包含的对象的方法,如果它们不是指针,那么这似乎是一个脆弱的解决方案。如果你想要这样的行为,你最好使用Boost Pointer Container库来提供这种确切的行为。标准库不是因为容器本身不知道它们是否控制包含的指针 - 你需要将指针包装成一个知道的类型 - 即智能指针。