以下代码有何作用?
obj *x = new obj[100];
delete x; // Note the omission of []
是否只删除数组中的第一个元素?
答案 0 :(得分:11)
上面的代码表现出未定义的行为:它应该是
delete[] x;
因为分配是使用new[]
完成的。
使用正确的运算符时,指针指向的整个数组将被删除:
obj *x = new obj[100];
delete[] x; // The entire array gets deleted
答案 1 :(得分:9)
即使它是未定义的行为,您也应该注意最可能的结果(为了调试此类问题)。
通过new Object[100]
创建数组时,首先分配内存。默认行为(假设没有覆盖默认分配器)是简单地调用malloc(100 * sizeof(Object))
。之后,需要在每个Object
大小的区域调用Object
的构造函数。这是一个重要的细节:内存分配一次,但构造函数在100个位置调用。
当通过malloc
分配块时,无法将其分段释放。只有对free(block)
的调用才会释放该内存。如果关键字delete
调用free
,则C ++关键字new
会在内部调用malloc
。因此,删除数组的正确方法是调用delete [] array
。那么,如果你致电delete array
会怎样?可能的答案是内存将被释放(所有内容,而不仅仅是第一个元素),但只会调用一个析构函数:第一个元素的析构函数。
显然,有很多事实需要考虑。 new
和delete
不一定与malloc
和free
绑定。它们可能使用特定体系结构或操作系统特有的系统调用。 (特别是,Windows在其C API中具有malloc
和free
之外的一整套堆管理功能。)我只是使用malloc
和free
演示了示例因为这是我在单步执行代码时最常见的。例如,Visual Studio允许您进入new
调用并实际查看new
函数代码。 (这是另一个重要细节。new
和delete
只是函数调用,在很多情况下甚至可以覆盖。)
你可以用这个小程序演示这个概念。只需创建一个Object
类,在构造函数中输出一些东西,并在析构函数中输出其他内容。
int main(int argc, char** argv)
{
Object* o = new Object[4];
delete o;
return 0;
}
我运行它,果然:构造函数被调用了4次,析构函数被调用了一次。
答案 2 :(得分:-1)
此代码在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;
}