【问题标题】:C++ template destructors for both primitive and complex data types原始数据类型和复杂数据类型的 C++ 模板析构函数
【发布时间】:2010-09-15 05:26:08
【问题描述】:

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

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

我希望能够做类似的事情

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

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

我可以这样做吗?我可以不使用智能指针吗?

再次感谢您的意见。

【问题讨论】:

  • 顺便说一句,“MyContainer blah();”定义函数原型,而不是变量。要声明变量,请删除括号。
  • C++ - 无法决定的语言选择:/

标签: c++ templates


【解决方案1】:

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

shared_ptr 应该注意在复杂类型被破坏时适当地删除它。当原始类型被破坏时,什么都不会发生。


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

【讨论】:

  • 我在堆上做一个数组,但我可能会去一个 STL 向量。一个相关的问题是“STL 是如何做到的?”。
  • STL 容器在自身被破坏时将破坏它们所包含的元素。 STL 容器不会获得指针的所有权。谁知道指针指向什么,不一定是需要删除的东西。例如,如果你在内存中有一张图片,你可能有调色板信息
  • 存储在其中,有一个指向它的指针。这不属于指针,不应该被删除。因此,对于您知道指向您分配的内存的指针,您总是必须自己删除它们。 shared_ptr 是不同的,它们旨在用于他们管理的对象的地方
  • 需要某种清理(通常,但不总是通过执行删除)。
  • 在 cmets 中拟合答案很棘手,如果您还没有,您应该创建一个新问题!
【解决方案2】:

您很可能确实想在这里使用智能指针,它确实简化了问题。但是,就像练习一样,很容易确定给定类型是否为指针。粗略的实现(可能更优雅,但我不想引入 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;

};

【讨论】:

  • 这个答案几乎是完美的。它确实正确地删除了指针和原始数据类型。但是,我似乎无法让它没有 valgrind-error-free。 valgrind 错误相当迟钝,但我会继续使用它,看看我是否能弄清楚发生了什么。
【解决方案3】:

可以做到,但这是相当高级的东西。 您需要使用 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 中使用的具有任何其他特定删除要求的任何其他类型实现特征。祝你好运!如果你解决了,请告诉我们你是如何做到的。

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      delete 用于释放先前使用new 分配的内存。此处不需要使用 delete,当 blah 和 complexBlah 超出范围时,它们会自动销毁。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-14
        • 2016-01-21
        • 1970-01-01
        • 1970-01-01
        • 2018-03-17
        • 2012-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多