C ++中的delete vs delete []运算符


135

C ++中的deletedelete[]运算符有什么区别?



7
delete和delete []的问题是我喜欢智能指针的原因之一,并且vector<>我会尽可能使用而不是数组。
David Thornley 2010年


@DavidThornley如果您使用的是智能指针,则仍然需要了解不写eg的意义std::unique_ptr<int>(new int[3]),因为它会调用delete未定义行为的常规数组。相反,您需要使用std::unique_ptr<int[]>
Arthur Tacca

Answers:


150

delete运营商释放内存,并呼吁与创建一个对象析构函数new

delete []操作者解除分配存储器和析构函数调用用于与创建的对象的阵列new []

使用delete上的指针返回通过new []delete []通过返回的指针new导致不确定的行为。


3
我想知道是否在像int或char这样的原始类型的new []数组上使用delete也会导致未定义的行为。使用基本类型时,似乎数组大小没有存储在任何地方。
thomiel 2014年

21
如果该标准没有定义完成该操作后将发生的情况,则即使定义了编译器确定要执行的操作,它也定义为“未定义的行为”。另一个编译器可能会做完全不同的事情。
罗伯K

当我有一个像“ char ** strArray”这样的C字符串数组时,我犯了这个错误。如果像我一样有一个数组,则需要遍历该数组并删除/释放每个元素,然后删除/释放strArray本身。在我拥有的阵列上使用“ delete []”不起作用,因为它调用了DESTRUCTORS(如上面的评论和回答所指出),实际上并没有释放每个插槽。
卡蒂安妮

88

delete[]运算符用于删除数组。该delete运算符用于删除非数组对象。它(分别)调用operator delete[]operator delete函数以删除数组或非数组对象(最终)为数组元素或非数组对象的析构函数之后占用的内存。

下面显示了关系:

typedef int array_type[1];

// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;

// create and destroy an int
int *b = new int;
delete b;

// create and destroy an int[1]
int *c = new int[1];
delete[] c;

// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;

new创建一个阵列(这样,无论是new type[]new应用于阵列型构建体),所述标准长相对于operator new[]在阵列的元件类型的类或在全球范围内,并传递的存储器请求的量。它可能会请求比N * sizeof(ElementType)其想要的更多的请求(例如,存储元素的数量,因此稍后在删除时它知道完成了多少个析构函数调用)。如果该类声明一个operator new[]额外的内存量接受另一个size_t,则该第二个参数将接收分配的元素数量-它可以将其用于任何所需的目的(调试等)。

对于new创建非数组对象的,它将operator new在元素的类或全局范围内查找。它传递所请求的内存量(实际上sizeof(T)总是)。

对于delete[],它将检查数组的元素类类型并调用其析构函数。所operator delete[]使用的函数是元素类型类中的一个函数,或者如果在全局范围内没有该函数。

对于delete,如果传递的指针是实际对象类型的基类,则该基类必须具有虚拟析构函数(否则,行为未定义)。如果不是基类,则调用该类的析构函数,并使用operator delete该类或全局变量中的in operator delete。如果传递了基类,则将调用实际对象类型的析构函数,并使用operator delete在该类中找到的析构函数;如果不存在,operator delete则调用全局变量。如果operator delete类中的in具有第二个类型的参数size_t,它将接收要取消分配的元素数。


18

这是c ++ malloc/ freenew/ deletenew[]/中的allocate / DE-allocate模式的基本用法 delete[]

我们需要相应地使用它们。不过,我想补充这个特殊的理解之间的差额delete,并delete[]

1)delete用于取消分配为单个对象分配的内存

2)delete[]用于取消分配为对象数组分配的内存

class ABC{}

ABC *ptr = new ABC[100]

当我们说时new ABC[100],编译器可以获得有关需要分配多少个对象的信息(此处为100),并将为每个创建的对象调用构造函数

但是相应地,如果我们仅使用delete ptr这种情况,编译器将不知道ptr指向了多少个对象,并且最终将调用析构函数并删除仅1个对象的内存(不调用析构函数并释放剩余的99个对象)。因此将存在内存泄漏。

因此我们需要delete [] ptr在这种情况下使用。


3
这应该是正确的答案。没有其他答案提到明显的不同:“但是相应地,如果在这种情况下我们仅使用delete ptr,则编译器将不知道ptr指向多少个对象,最终将调用析构函数并仅删除1个对象的内存”
Don Larynx

1
我们如何在C语言中实现同一目标?
Dogus Ural'17-4-17

@DogusUral为什么?C中没有析构函数,因此仅free()此而已。如果使用伪析构函数模式,则必须使用for循环为每个对象调用一次。
Kotauskas

@DonLarynx的正确区别是将它们混合在一起会导致程序格式错误。一个实现可能知道要销毁多少个对象,或者可能不知道。可以知道它被称为错误,并中止程序以告诉您问题出在哪里。
卡雷斯

6

运算符deletedelete []分别用于销毁和创建的对象,newnew[]返回分配给编译器内存管理器可用的内存。

用创建的对象new必须用销毁,用delete创建的数组new[]应该用删除delete[]



0

delete用于单个指针,delete[]用于通过指针删除数组。 可以帮助您更好地理解。


-6

好吧..也许我认为这只是为了明确。操作员delete和操作员delete[]是区分的,但delete操作员也可以释放数组。

test* a = new test[100];
delete a;

并且已经检查过此代码没有内存泄漏。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.