C++ 中
delete
和 delete[]
运算符有什么区别?
delete
运算符释放内存并为使用new
创建的单个对象调用析构函数。
delete []
运算符释放内存并为使用new []
创建的对象数组调用析构函数。
在
delete
返回的指针上使用 new []
或在 delete []
返回的指针上使用 new
会导致未定义的行为。
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
或全局 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
指向了多少个对象,最终将调用析构函数并仅删除1个对象的内存(留下析构函数的调用和释放)剩余 99 个对象)。因此会出现内存泄漏。
所以在这种情况下我们需要使用
delete [] ptr
。
当我问这个问题时,我真正的问题是,“两者之间有区别吗?运行时是否必须保留有关数组大小的信息,因此它是否无法分辨我们指的是哪一个?”这个问题没有出现在“相关问题”中,所以为了帮助像我这样的人,这里是答案:“为什么我们甚至需要删除[]运算符?”
运算符
delete
和 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 //<-----