析构函数 - 我应该使用删除还是删除[]?

时间:2010-02-03 20:39:45

标签: c++ templates destructor

我正在编写一个模板类,它将指针作为输入并存储它。指针旨在指向由另一个类分配的对象,并将其传递给此包含类。

现在我想为这个容器创建一个析构函数。我应该如何释放此指针指向的内存?我无法知道它是一个数组还是一个元素的先验。

我是C ++的新手,所以请耐心等待。我一直使用C语言,而Java是我选择的OO语言,但在想要学习C ++和我的项目的速度要求之间,我已经使用了C ++。

将容器从模板更改为可以实现自己的析构函数的抽象类的容器是否更好?

11 个答案:

答案 0 :(得分:6)

如果您不知道它是否已分配newnew[],则删除它是不安全的。

您的代码似乎有效。例如,在我工作的一个平台上,差异仅在您拥有具有析构函数的对象数组时才有意义。所以,你这样做:

// by luck, this works on my preferred platform
// don't do this - just an example of why your code seems to work
int *ints = new int[20];
delete ints;

然后你这样做:

// crashes on my platform
std::string *strings = new std::string[10];
delete strings;

答案 1 :(得分:6)

您必须记录此类预期的使用方式,并始终按预期分配。您还可以将标志传递给对象,指定它应该如何销毁。另请参阅boost smart pointers,它可以为您处理这种区别。

答案 2 :(得分:5)

简短回答:

如果您使用新的[],则需要将[]与删除一起使用。

//allocate some memory
myObject* m = new myObject[100];

//later on...destructor...
delete m; //wrong
delete[] m; //correct

那是光秃秃的骨头,你可以看到的另一件事是boost。考虑到你不确定它是一个数组还是单个对象,也很难回答。你可以通过一个标志告诉你的应用程序是否使用删除或删除[]来检查这个。

答案 3 :(得分:2)

作为一般开发规则,您应该坚持设计,其中调用new的班级也应该调用delete

答案 4 :(得分:2)

你根本不应该删除它。如果您的类采用已初始化的指针,则删除它是不安全的。它甚至可能没有指向堆上的对象;调用deletedelete[]可能是灾难性的。

内存的分配和释放应该在同一范围内进行。哪个代码拥有并初始化您的类的实例也可能负责初始化和传入指针,而 delete所在的位置。

答案 5 :(得分:2)

  • 如果您使用delete分配了new
  • 如果您使用delete[]分配了new[]

在这些陈述之后,如果你仍有问题(也许你想要删除由其他人创建的对象),那么你违反了第三条规则:

  • 始终删除您创建的内容。推论,永远不要删除你没有创建的内容。

答案 6 :(得分:2)

(根据请求将我的评论转移到答案中。)

JonH的答案是正确的(关于在使用数组构造时仅使用数组销毁),所以也许你应该提供模板:一个用于数组,一个用于数组。

另一个答案是避免使用数组,而是期望单个实例可能是也可能不是自己清理后的正确集合,例如vector<>。

修改

从Roger Pate公然偷窃,我将补充说你可能需要使用一个智能指针,这相当于一个单项集合。

答案 7 :(得分:2)

如果你有一个带有指针的类,它将承担所有权,那么使用该类的合同需要包括一些东西。之一:

  • 接口需要指示指针指向的对象是如何分配的,以便新所有者可以知道如何安全地释放对象。这个选项的优点是保持简单(无论如何在一个层面上),但它不灵活 - 类无法处理静态对象的所有权以及动态分配的对象。

  • 接口需要包含一种机制,其中可以通过赋予类的指针来指定释放策略。这可以简单到提供一个传递函数(或者甚至是一个普通的旧函数指针)的机制,该函数将被调用以释放对象(最好是在传入指针本身的同一函数/构造函数中)。这使得类可以说使用起来更复杂(例如,在指针上调用delete的默认策略可能会使其在大多数用途中像选项1一样易于使用)。现在,如果有人想给类指定一个静态分配的对象,他们可以传入一个无操作的函子,这样当类想要释放它时没有任何反应,或者如果对象是delete[]操作的函子由new[]等分配

答案 8 :(得分:1)

由于C ++中的指针没有告诉我们它是如何分配的,是的,没有办法决定使用什么解除分配方法。解决方案是为用户提供有希望知道内存分配方式的选择。看一下Boost smart ptr库,特别是shared_ptr构造函数的第二个参数,这是一个很好的例子。

答案 9 :(得分:0)

像boost shared_pointer这样的智能指针已经涵盖了这个,你能用吗? linky

答案 10 :(得分:0)

简单地说,只给出一个指向动态分配内存的指针,就无法确定如何安全地解除分配。指针可以通过以下任何一种方式分配:

  • 使用新
  • 使用new []
  • 使用malloc
  • 使用用户定义的功能

在您可以释放内存之前的所有情况下,您必须知道它是如何分配的。