delete
和delete[]
运算符有什么区别?delete
和delete[]
运算符有什么区别?delete
操作符释放内存并调用使用 new
创建的单个对象的析构函数。
delete []
操作符释放内存并调用使用 new []
创建的一组对象的析构函数。
在指向由 new []
创建的指针上使用 delete
或在指向由 new
创建的指针上使用 delete []
都会产生未定义的行为。
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)
的内存量。如果该类声明了一个额外接受另一个size_t
的内存量的operator new[]
,那么第二个参数将接收分配的元素数-它可以将其用于任何目的(调试等...)。new
,它将在元素类或全局范围内查找operator new
。它传递所请求的内存量(始终精确为sizeof(T)
)。delete[]
,它查找数组元素类类型并调用它们的析构函数。使用的operator delete[]
函数是元素类型类中的函数,如果没有,则在全局范围内查找。delete
,如果传递的指针是实际对象类型的基类,则基类必须有虚析构函数(否则,行为是未定义的)。如果它不是基类,则调用该类的析构函数,并使用该类中的operator delete
或全局operator delete
。如果传递了一个基类,则调用实际对象类型的析构函数,并使用在该类中找到的operator delete
,如果没有,则调用全局operator delete
。如果类中的operator delete
具有第二个类型为size_t
的参数,则它将接收要释放的元素数。这是C++中使用分配/释放模式的基本用法,包括malloc
/free
、new
/delete
、new[]
/delete[]
。
我们需要相应地使用它们。但我想补充一下delete
和delete[]
之间的不同理解:
1)delete
用于释放为单个对象分配的内存
2)delete[]
用于释放为对象数组分配的内存
class ABC{}
ABC *ptr = new ABC[100]
当我们使用new ABC[100]
时,编译器可以获取需要分配多少对象的信息(即100),并将为创建的每个对象调用构造函数。
但是,如果我们对于这种情况仅使用delete ptr
,编译器将不知道指针ptr
所指的对象有多少个,最终只会调用一个析构函数并删除一个对象的内存(留下了其他99个对象的析构函数的调用和释放)。因此,会出现内存泄漏。
因此,在这种情况下,我们需要使用delete [] ptr
。
free()
释放这个和那个。如果你使用伪析构函数模式,你需要使用一个for
循环为每个对象调用一次。 - Kotauskasdelete
和 delete []
操作符分别用于销毁使用 new
和 new[]
创建的对象,并将剩余的已分配内存返回给编译器的内存管理器。
使用 new
创建的对象必须使用 delete
销毁,而使用 new[]
创建的数组应该使用 delete[]
进行删除。
C++ delete[] 运算符可确保调用使用 new[] 分配的所有对象的析构函数。以下示例演示相同的内容。同时,如果类具有非默认析构函数以释放获取的资源,则必须首选使用 delete[](如果先前使用 new[])。否则,可能会导致内存泄漏。
常见代码:
#include <iostream>
using namespace std;
class memTest{
public:
static int num;
memTest(){
cout<<"Constructor from object " << num++ << endl;
}
~memTest(){
cout<<"Destructor from object " << --num << endl;
}
};
int memTest::num=0;
例如1:使用new[]和delete可能导致未定义行为。
int main() {
memTest* Test1=new memTest[3];
delete Test1; //<-----
return 0;
}
输出 1:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2 //<-----
示例2:正确的做法是使用new[]和delete[]。
int main() {
memTest* Test1=new memTest[3];
delete[] Test1; //<-----
return 0;
}
输出2:
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2
Destructor from object 1 //<-----
Destructor from object 0 //<-----
vector<>
代替数组是因为delete和delete[]容易出问题的原因之一。 - David Thornleystd::unique_ptr<int>(new int[3])
的代码,因为它将在数组上调用常规的delete
操作,这是未定义的行为。相反,您需要使用std::unique_ptr<int[]>
。 - Arthur Taccastd::array
,因为它在概念上更符合该用例,并且很可能更快。 - user904963