C++中delete和delete[]的区别

45

可能重复问题:
C++中delete和delete[]运算符的区别

我编写了一个类,其中包含两个指针,一个是char* color_,另一个是vertexesset* vertex_,其中vertexesset是我创建的一个类。在析构函数中,我一开始写了:

delete [] color_;
delete [] vertex_;

当我调用析构函数时,程序发生了分段错误。

后来我将析构函数改成了:

delete [] color_;
delete vertex_;

现在它能够正常工作了。这两种方法的区别是什么?


9
你能发一下你分配这两个指针的代码吗?也就是说,新部分的代码。 - clamp
2
你有遵循三法则吗? - fredoverflow
1
https://dev59.com/JHI_5IYBdhLWcg3wDOdC - sbi
9个回答

69

当你用new创建了一个数组类型时,你需要使用delete []进行删除,而在没有使用new创建的情况下,只需使用delete即可。例如:

typedef int int_array[10];

int* a = new int;
int* b = new int[10];
int* c = new int_array;

delete a;
delete[] b;
delete[] c; // this is a must! even if the new-line didn't use [].

9
+1 是指提到 int_array 的情况。 - Bart van Ingen Schenau
2
从评论中复制到另一个答案:使用数组typedef是一个坏主意,但提及它并不是一个坏主意,因为人们会被它咬伤。此外,重点是即使你编写了 new,有时也需要编写 delete[] - etarion
有人编辑了typedef - 现在的方式(以及最初的方式)是正确的,请在编辑之前尝试您的“修复”。请参见http://ideone.com/fYh6MK与http://ideone.com/w9fPKr。 - etarion
如果你有以下内容,我很想知道你需要什么:char ** strings = new char * [2]; strings [0] = new char [10]; strings [1] = new char [10]; delete [] strings会清除所有内存还是只清除字符串数组,让我清除两个char数组? - Mahen
@Mahen 只是删除字符串的指针,所以请先删除数组内容。 - etarion

25

deletedelete[] 不是一回事!维基百科在 这里 有简短的解释。简而言之,delete [] 对分配的数组中每个元素都调用析构函数,而 delete 假设你只有一个实例。你应该使用 new foo[] 来分配数组,并使用 delete[] 来删除它们;对于普通对象,请使用 newdelete。在非数组上使用 delete[] 可能会导致严重问题。


3
这应该是答案,它实际上解释了不同之处。谢谢。 - Andrew
1
是的,这个帖子因为晚了2分钟而失去了40个赞。需要注意的是,你不能使用delete[]作为处理原始指针的万能解决方案。 - jiggunjer
为什么 C++ 运行时不直接区分数组和非数组类型,这样程序员就可以使用一个单独的“delete”语句? - Carl G
这必须是编译器的问题,而不是运行时。运行时只能看到对 mallocfree 的调用(例如)。 - EmeryBerger

9
  • 如果你使用malloc()分配内存,你需要使用free()释放内存。
  • 如果你使用new分配内存,你需要使用delete释放内存。
  • 如果你使用new[]分配内存,你需要使用delete[]释放内存。
  • 如果你使用placement-new构造对象,你需要直接调用析构函数。
  • 如果使用vector比使用new[]更合适,则使用vector。
  • 如果使用智能指针比手动调用delete更合适,则使用智能指针(但仍需要调用new)。匹配的delete将在智能指针中处理。

https://isocpp.org/wiki/faq/freestore-mgmt


如果你使用new进行分配,那么你需要使用delete进行释放 - 但并非总是如此,请查看我的回答。 - etarion
@etarion:我在你的回答中没有看到任何与此陈述相矛盾的内容;你对类型别名的使用仍然会调用new[]而不是new,类型别名只是混淆了这一事实,可能是个坏主意(甚至提到它都是)。 - Clifford
1
使用数组 typedef 不是一个好主意,但提到它也不是一个坏主意,因为人们会受到它的影响。此外,重点是即使你编写了 new,有时你还需要编写 delete[] - etarion

5

如果你使用了new[](例如动态数组)在堆上分配内存,那么你必须使用delete []

如果你使用了new操作符,则必须使用没有方括号的delete操作符。

这与删除内置类型或自定义类无关。


使用delete[]删除使用new创建的任何东西不会有害,但段错误必须有其他原因。 - ypnos
8
你从哪里得到这个想法,认为它不会疼痛?这是错误的。 - etarion
3
在哪个宇宙中,未定义的行为不会造成伤害呢? :) (注:该句话是一种反问表达方式,意思即在任何宇宙中未定义的行为都会造成伤害。) - fredoverflow
3
未定义行为总是会对代码造成伤害,只是不一定会立即显现出来。 - Fred Larson

2
当我们想要释放一个指向对象的指针所分配的内存时,使用"delete"。
int * p;
p=new int;

// now to free the memory 
delete p;

但是当我们为对象数组分配内存时,例如:
int * p= new int[10]; //pointer to an array of 10 integer

然后释放等于10个整数的内存:

 delete []p;

注意:即使使用delete p;也可以释放内存,但它仅会释放第一个元素的内存。


new int(10) 分配了一个单独的 int,而不是一个由 10 个 int 组成的数组。 - CB Bailey
注意:即使使用delete p;也可以释放内存,但它只会释放第一个元素的内存。这个注释是错误的。以下问题解释了原因:https://stackoverflow.com/questions/4480722/should-new-new-match-delete-delete - drescherjm

1

3
如果你还没有《Effective C++》,现在就去买吧! - fredoverflow

1

0
现在它运行得很好。 如果它确实运行,那更多是侥幸而非判断力,你确定它真的在工作吗?
每个对象的析构函数必须被调用,delete[] 运算符使用 new[] 设置的信息来确定要销毁多少个对象。因此,虽然单独使用 delete 可能会回收内存(尽管是否回收取决于具体实现),但它可能不会调用为每个分配的对象调用析构函数。
当调用 new 或 new[] 时,可以包含关于对象分配方式的信息,以便无论如何都使用正确的删除形式,但这又取决于具体实现,不能保证。

0
此外,如果不是必须的话,考虑不使用指针。例如,可以用std::string替换char*,如果您的vertexesset成员不是多态的,可以将其作为成员对象。在这种情况下,您根本不需要使用delete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接