8

如果我们分配一个大小为 1 的对象,如下所示

int *arr = new int[1];

operator delete[]我们应该使用or删除对象operator delete吗?

我担心的原因是编译器是否足够聪明,可以将语句转换为单个元素分配int *arr = new int,这会导致调用operator delete[]UB。

用户案例:

我有一个指针,我最终会以多种方式分配它,但最终希望将其删除。所以想知道,对于单元素分配,如果我一直使用,我是否int *arr = new int[1]可以一直安全地使用operator delete[]

笔记

您能否请我参考标准以支持您的答案?

4

6 回答 6

13

你必须使用delete[]而不是delete。不允许编译器更改new int[1]new int.

(作为intPOD 类型,很有可能在幕后做同样的事情,但如果是这种情况,那么new inton and on an也会做同样的事情。)new int[1]delete[]int*deleteint*

ISO/IEC 14882:2011 5.3.5 [expr.delete] / 2:

在第一种选择(delete object)中,操作数的值可以是空指针值,指向由先前的new-expressiondelete创建的非数组对象的指针,或指向表示基的子对象(1.8)的指针此类对象的类别(第 10 条)。如果不是,则行为未定义。

int[1]数组对象一样,如果您尝试使用deleteand not删除它delete[],则行为未定义。

于 2013-07-12T07:25:57.970 回答
6

规则很简单:

  1. 始终平衡 anew和 adelete
  2. 始终平衡 anew[]和 adelete[]

否则你会得到未定义的行为

没有例外;evennew[1]必须与 a 平衡delete[],并且new[0]必须删除,因为编译器仍然可以保留存储。

于 2013-07-12T07:27:41.193 回答
2

您必须使用delete[].

C++11 5.3.5 删除

::opt 删除强制转换表达式

::opt delete [ ] 强制转换表达式

第一种选择用于非数组对象,第二种选择用于数组。

包含一个元素的数组仍然是数组。

于 2013-07-12T07:27:45.957 回答
2

delete[]我们应该使用运算符还是删除对象operator delete

operator delete[]. 您已经分配了一个s数组int因此没有其他选项可以正确释放它。使用operator delete会调用未定义的行为。

于 2013-07-12T07:26:28.320 回答
1
int *arr = new int[1];

由于您使用[]for 分配,因此您也需要使用[]for delete

内存泄漏

由新表达式创建的对象(具有动态存储持续时间的对象)会一直存在,直到新表达式返回的指针用于匹配的删除表达式。

所以你应该使用delete[]释放内存,否则你会得到未定义的行为。

并且(以防万一),如果编译器足够聪明,可以接受int * arr = new int[1]as int,它必须足够聪明才能delete[] arr接受arras delete arr但是,没有什么delete可以区分arrfromint*arr = new int[1]int*arr = new int。在将表明它[]delete

于 2013-07-12T07:44:39.207 回答
0

不,它不安全,它可能会导致一些不需要的情况。
例如,内存中可能在int/char/float指针指向的位置旁边有一些数据(...)。那时如果你使用delete [] 了,那么它可能会尝试删除该数据,如果它是一个整数,对于其他数据类型它会导致意外错误。

例子:

int *ptr = new int;
int a = 20;
char c = 'e';
*ptr = 10;
delete [] ptr;

c和变量有a可能存储在指针ptr指向的位置旁边,如果a存储在它旁边,那么它a也会删除“”,如果存在其他数据类型,则会导致意外的运行时结果。

所以建议delete[]仅用于删除使用新数据类型分配的内存[]。希望这很有用。

于 2013-07-12T10:07:26.417 回答