下面的代码有什么作用?
obj *x = new obj[100];
delete x; // Note the omission of []
它是否只删除数组中的第一个元素?
上面的代码表现出未定义的行为:它应该是
delete[] x;
因为分配是用new[]
.
当您使用正确的运算符时,指针指向的整个数组将被删除:
obj *x = new obj[100];
delete[] x; // The entire array gets deleted
即使它是未定义的行为,您也应该注意最可能的结果(为了调试此类问题)。
当您通过 创建数组时new Object[100]
,首先分配内存。默认行为(假设没有覆盖默认分配器)是简单地调用malloc(100 * sizeof(Object))
. 之后,Object
需要在每个Object
大小的区域上调用 for 的构造函数。这是一个重要的细节:内存被分配一次,但构造函数在 100 个位置被调用。
当一个块通过 分配时malloc
,它不能被分段释放。只有调用free(block)
才会释放该内存。如果关键字调用,则C++ 关键字在delete
内部调用. 因此,删除数组的正确方法是调用. 那么,如果你打电话会发生什么?可能的答案是内存将被释放(全部释放,而不仅仅是第一个元素),但只会调用一个析构函数:第一个元素的析构函数。free
new
malloc
delete [] array
delete array
显然,有很多事实需要考虑。new
anddelete
不一定与malloc
and绑定free
。他们可能使用特定架构或操作系统特有的系统调用。(特别是 Windows,在其 C API之外malloc
和内部都有一整套堆管理功能。)我只是用and演示了这个示例,因为这是我在单步执行代码时最常看到的。例如,Visual Studio 允许您进入调用并实际查看函数代码。(这是另一个重要的细节。只是简单的函数调用,在很多情况下你甚至可以覆盖它。)free
malloc
free
new
new
new
delete
你可以用这个小程序演示这个概念。只需创建一个Object
在构造函数期间输出某些内容并在析构函数期间输出其他内容的类。
int main(int argc, char** argv)
{
Object* o = new Object[4];
delete o;
return 0;
}
我运行它,果然:构造函数被调用了 4 次,而析构函数被调用了一次。
此代码在 GCC 上表现出明确的行为,即删除第一个对象。
#include <iostream>
#include <stdlib.h>
#include <time.h>
class myclass {
public:
int i;
myclass(){
std::cout <<"myclass constructed \n";
this->i = rand() % 100;
std::cout<<this->i;
}
~myclass(){
std::cout <<"myclass destroyed\n";
std::cout<<this->i;
}
};
int main()
{
myclass * pt;
srand ( time(NULL) );
pt = new myclass[3];
delete pt;
return 0;
}