目录
引入
原理
引入
大家先看如下代码:
class A
{
private:int _a = 0;
};int main()
{A* arr1 = new A[10];delete arr1;return 0;
}
可以发现这里new了一个数组但却用delete释放。先看运行结果:
可以看到程序正常结束并没有崩 ,别急我们再给它加一个析构。
class A
{
public:~A(){_a = -1;}
private:int _a = 0;
};int main()
{A* arr1 = new A[10];delete arr1;return 0;
}
可以发现只是多了一个析构就崩了,为什么会这样?
原理
我们先看一下数组所开辟的大小,这是没加析构:
这是加析构:
A类的大小是4个字节,我们开10个空间大小就应该是40个字节,通过上面的可以发现没加析构的大小和预期的一样,写析构的大小居然多出来了4个字节。
我就直接说了那4个字节是用来存放数据的个数的。我们可以看一下它的内存。
通过上面的图可以看出在arr1数组上面确实有一块空间大小是4个字节存放的是数据个数。编译器为这么做是因为析构一般用于资源释放,前面的数据个数就代表析构几次(如果不加前面的4个字节编译器就不知道要析构几次)。即arr1并不是开辟空间的首地址,但释放空间只能从首地址开始所以就会崩溃。
没写析构为什么不多开这4个字节,这是因为没有写析构编译器认为这些空间没有资源可释放,它自己生成的析构函数也并不需要做什么事情然后编译器一优化就直接省略了析构,所以就arr1即使首地址这时候释放就没事。
上面所叙述的只是对于自定义类型的问题,对于内置类型呢?
可以看到并没有发生崩溃。但是我并不建议这样写,就正常写就行。