2

在一个相关问题中,我询问了有关创建通用容器的问题。使用多态模板似乎是正确的方法。

但是,我一生都无法弄清楚应该如何编写析构函数。我希望分配的内存的所有者是容器,即使示例构造函数接受一个数组T(连同它的维度),在其他点分配。

我希望能够做类似的事情

MyContainer<float> blah();
...
delete blah;

MyContainer<ComplexObjectType*> complexBlah();
...
delete complexBlah;`

我可以做这样的事情吗?我可以在没有智能指针的情况下做到这一点吗?

再次感谢您的意见。

4

5 回答 5

4

如果您想存储指向复杂类型的指针,我建议您将容器用作: MyContainer<shared_ptr<SomeComplexType> >,而对于原始类型,只需使用MyContainer<float>.

shared_ptr应该注意在复杂类型被破坏时适当地删除它。当原始类型被破坏时,不会发生任何花哨的事情。


如果您以这种方式使用容器,则不需要太多的析构函数。您如何将物品存放在容器中?您使用 STL 容器还是堆上的数组?STL 容器会自行删除。如果你删除数组,这将导致每个元素的析构函数被执行,如果每个元素都是 a shared_ptrshared_ptr析构函数将删除它自己持有的指针。

于 2008-10-04T00:40:43.567 回答
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;

};

于 2008-10-04T08:30:42.447 回答
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 中使用的具有任何其他特定删除要求的任何其他类型实现特征。祝你好运!如果你解决了它,请告诉我们你是如何做到的。

于 2008-10-04T00:32:15.470 回答
0

如果您不想使用智能指针,您可以尝试部分模板专业化,它让您编写一个仅在使用指针类型实例化容器时使用的模板。

于 2008-10-04T03:37:04.067 回答
0

delete 用于释放先前分配的内存new。您不需要在这里使用 delete,当 blah 和 complexBlah 超出范围时,它们将自动被销毁。

虽然yrp 的回答向您展示了一种使用模板专业化来删除包含的对象的方法,如果它们是指针,而不是如果它们不是,这似乎是一个脆弱的解决方案。如果你想要这样的行为,你最好使用Boost Pointer Container库,它提供了这种确切的行为。标准库不这样做的原因是因为容器本身不知道它们是否控制包含的指针-您需要将指针包装在确实知道的类型中-即智能指针。

于 2008-10-10T17:21:27.040 回答