删除模板类型

时间:2016-02-09 16:18:34

标签: c++ class templates

我有一个看起来像这样的泛型类:

template <class T>
class Example
{
  private:
    T data;
  public:
    Example(): data(T())
    Example(T typeData): data(typeData) 
    ~Example()

    // ...
};

我对如何为这样的事情实现解构器感到有些困惑。具体来说,由于T是任何类型,它可能是在堆栈上分配的内存(通过无参数构造函数创建的Example总是如此)或在堆上。

例如,如果客户端将T的类型设为int*并提供指向动态内存的指针,我如何知道在delete上调用data为如果客户端将类型设置为int

,则反对

5 个答案:

答案 0 :(得分:7)

最简单的答案是:不要。不要试图猜测用户并做一些他们可能没想到的事情。采用与标准容器相同的策略:假设T正确清理。

如果客户端代码编写正确,它将使用RAII类(如智能指针)自动和正确管理内存和其他资源。如果不是,您不能希望在提供商代码中修复它。

让您的课程与std::unique_ptrstd::shared_ptr一起使用,以及任何其他自定义RAII课程,并让您的客户自己进行管理。毕竟,如果他们想要存储非拥有指针怎么办?

答案 1 :(得分:2)

您可以使用模板专业化。

template <class T>
class Example
{
  private:
    T data;
  public:
    Example()
        : data(T())
    {}

    Example(T typeData): data(typeData)
    {}
};

template <class T>
class Example<T*>
{
  private:
    T* data;
  public:
    Example() : data(nullptr){}
    Example(T* typeData): data(typeData) {}
    ~Example()
    {
        delete data;
    }
};

int main() 
{
    Example<int> e;
    Example<int*> e2;

    return 0;
}

答案 2 :(得分:0)

您可以不像标准库那样担心它。例如,如果创建指针向量,则在让向量超出范围之前,您负责删除它们。然后人们可以决定他们是否甚至想要删除它(也许它是临时的排序和其他东西拥有对象)。他们也可以使用智能指针,这样vector就可以通过智能指针的析构函数来破坏对象。

在这种情况下,少即是多。你不必做任何复杂的事情。您不必维护模板的多个版本。最后,模板的用户当然还有更多的控制权和责任感。

答案 3 :(得分:0)

当您需要std::unique_ptr来持有拥有指针时,我建议您将T用于Example。如果T是一个原始指针,那么它根本就不拥有,不应该删除它。

如果您需要Example初始化指针,请将其专门用于std::unique_ptr并在默认构造函数中调用std::make_unique

template<typename T>
class Example<std::unique_ptr<T>> {
    Example() : data{std::make_unique<T>()} {}

    /* rest of the class */
};

如果你这样做,你不应该让你的班级专门为T*new,因为你不能初始化非拥有指针。您应该在构造函数中接收它,如果您不希望它为null,可能会禁用原始指针的默认构造函数。

template<typename T>
class Example<T*> {
    Example() = delete;
    Example(T* data_) : data{data_}

    /* data is not an owning pointer. No need for a destructor */

    /* rest of the class */
};

如果遵循这些规则,您应该对内存管理没有任何问题。

答案 4 :(得分:0)

使用可按类型选择的内存释放帮助程序模板类。 您不需要使用Template Specialization对您的课程进行加分。 你只能写一个班级。

const

但需要知道新调用的形式,所以使用删除或删除[]。