C++ 为什么阵列有一个特殊的new和delete?
使用C++ 为什么阵列有一个特殊的new和delete?,c++,arrays,memory-management,new-operator,C++,Arrays,Memory Management,New Operator,使用delete而不是delete[]有什么问题 在分配和释放阵列的掩护下是否发生了一些特殊的事情 为什么它不同于malloc和free?使用new[]创建的对象必须使用delete[]。使用delete在数组上未定义 有了malloc和free,情况就更简单了。只有一个函数释放分配的数据,也没有调用析构函数的概念。这种混淆是因为delete[]和delete看起来很相似。实际上,它们是两个完全不同的函数 使用delete不会调用正确的函数来删除内存。它应该调用delete[](void*),但
delete
而不是delete[]
有什么问题
在分配和释放阵列的掩护下是否发生了一些特殊的事情
为什么它不同于
malloc
和free?使用new[]
创建的对象必须使用delete[]
。使用delete
在数组上未定义
有了malloc和free,情况就更简单了。只有一个函数释放分配的数据,也没有调用析构函数的概念。这种混淆是因为delete[]
和delete看起来很相似。实际上,它们是两个完全不同的函数
使用delete不会调用正确的函数来删除内存。它应该调用delete[](void*)
,但它会调用delete(void*)
。因此,对于分配给new[]
[16.13]我可以在什么时候删除[]
吗
正在删除某些内置类型的数组
(字符、整数等)
不
有时程序员认为
delete[]p
中的[]
编译器将调用适当的
中所有元素的析构函数
数组。因为这个理由,他们
假设某个内置的
可以选择char
或int
等类型
删除
d而不使用[]
。例如,他们
假设以下代码有效:
void userCode(int n) {
char* p = new char[n];
...
delete p; // ← ERROR! Should be delete[] p !
}
但是上面的代码是错误的,而且
在运行时可能导致灾难。在里面
特别是,所调用的代码
delete p
是操作员删除(void*)
,
但是需要的代码
delete[]p
是运算符
删除[](无效*)
。默认行为
因为后者叫前者,
但允许用户更换
后者具有不同的行为(在
在这种情况下,他们通常也会
替换中相应的新代码
操作员new[](大小)
)。如果他们
替换了delete[]
代码,以便
与删除不兼容
密码,你打错电话了
(即,如果您说删除p
而不是
比删除[]p
),您可能会
在运行时发生灾难
为什么delete[]
首先存在?
无论您选择x还是y:
char * x = new char[100];
char * y = new char;
两者都存储在char*
类型化变量中
我认为,决定“代码>删除删除/代码>,和<代码>删除[]/CODE >是一系列有利于C++效率的决定。这样就没有强制执行的价格来查找正常删除操作需要删除多少
拥有2个
new
和new[]
似乎只是为了对称而选择delete
和delete[]
才合乎逻辑 不同之处在于delete
只会删除整个内存范围,但只会调用一个对象的析构函数delete[]
将删除内存并为每个对象调用析构函数。如果不对数组使用delete[]
,那么将资源泄漏引入应用程序只是时间问题
编辑更新
根据标准,将分配有
new[]
的对象传递给delete
是未定义的。可能的行为是它将按照我所描述的那样行动 > P>使用“代码>新[] /代码>分配数组时,实际上是在告诉C++数组的大小。当您使用malloc
时,您会告诉它分配了多少内存。在前一种情况下,基于数组大小进行释放是没有意义的。在这种情况下,确实如此。但是,由于数组指针与单个对象指针没有区别,因此需要一个单独的函数。new
和delete
不同于malloc
和free
,因为malloc
和free
只分配和释放内存;它们不调用CTOR或DTOR。此要求的原因是历史原因,因为新类型
和新类型[大小]
返回需要以不同方式清理的不同内容
考虑一下这个代码
Foo* oneEntry = new Foo;
Foo* tenEntries = new Foo[10];
这两个函数都返回一个Foo*
指针,不同的是第二次调用将导致Foo构造函数被调用10倍,并且内存大约是原来的10倍
因此,现在要释放对象
对于单个对象,您可以调用delete-例如delete-oneEntry
。这将调用对象析构函数并释放内存
但问题是,oneEntry和tenEntries都只是Foo
指针。编译器不知道它们是指向一个、十个还是一千个元素
当您使用特殊语法delete[]
时。这会告诉编译器“这是一个对象数组,计算出数量,然后将其全部销毁”
真正发生的是,对于新类型[size]
,编译器将“size”秘密存储在其他地方。调用delete[]时,它知道这个秘密值存在,因此它可以找出该内存块中有多少个对象,并对它们进行销毁
然后您可能会问“为什么编译器不总是存储大小?”
这是个很好的问题,它可以追溯到C++的早期。对于内置类型(char、int、浮点等),有以下的愿望:C++是有效的;p>
int* ptr = new int;
free(ptr);
int* ptr = (int*)malloc(sizeof(int) * someSize);
delete ptr;
这背后的原因是人们希望提供返回动态分配内存的库,而这些库的用户将无法知道是否使用free/delete
这种渴望