C++中delete与delete[]的问题

1.C++中delete之后指针指向问题

在C++中经常需要用new进行动态内存分配,然后使用delete或者delete[]进行内存的释放。但是实际上delete并没有删除指针本身,而是标记指针指向的那块内存区域可用,如果不讲指针置为空的话,便会造成一定的风险。例如:delete ptr;执行之后,ptr指针仍然存在,并且会随机指向一个地址,如果后续程序仍然需要访问ptr这个指针就会造成风险。

通过下面简单的例子就可以看出来:

#include<iostream>

using namespace std;

 

void main()

{

int *ptr = new int;//为ptr分配1个int的内存

*ptr = 5;

cout << "删除指针前指针地址:" << ptr<<endl;

delete ptr;//删除指针

cout << "删除指针后指针地址:" << ptr << endl;

}

上面这个小例子足以说明这个问题,因此在书写程序的时候应当注意将指针指向nullptr。

  1. C++中delete与delete[]的区别以及滥用造成的问题

C++中提供delete和delete[]两种方式对内存进行释放,但他们只能释放new动态分配的内存。这两种方式分别适用于不同的情况,delete是对指向单个元素或者对象的指针进行释放,如上1中所示。而delete[]是对数组或者对象数组进行内存的释放,例如:

Int *ptr=new int[4];//分配4个int型内存空间

delete[] ptr;//释放该空间

对于普通数组型的内存释放,使用delete和delete[]他们没有多大区别,因为它们直接将分配的内存块标记成可用。但是对于对象数组错误的使用delete和delete[]便会出现一些问题。

第一种情况:对单个对象使用delete进行内存释放

例如:

#include<iostream>

using namespace std;

 

class Test{

public:

~Test() { cout << "调用析构函数" << endl; }

};

 

void main()

{

Test *ptr=new Test;//分配一个对象长度的内存

delete[] ptr;//用delete[]释放该内存

}

在上面的简短例子中,建立了一个Test类用于测试,其中仅仅有一个析构函数。然后用new分配了一个Test类对象的空间,再用delete[]对内存进行释放,此时会出现无限次调用析构函数的情况。造成这个问题的原因是什么呢?首先我们从使用new对对象数组进行内存分配方式说起。

例如:Test *ptr=new Test[10];//使用new分配10个Test对象长度的内存

实际上执行的时候是new[](10*sizeof(Test)+4),即分配了(10*sizeof(Test)+4)长度的内存空间,多处的4个字节用于存储10这个数字,在对对象数组进行析构的时候便知道调用析构函数的次数。而当使用delete[]对单个对象进行释放时,编译器认为删除的时一个对象数组,便会访问Test分配内存空间的后面4个字节,来知道进行析构的次数。然而后面四个字节并不是一个赋予了的值而是一个随机值,所以就出现了无限析构的错误。那么具体析构多少次呢?这就要由那四个字节中的垃圾数据来决定了。

第二中种情况:使用delete对对象数组进行释放

#include<iostream>

using namespace std;

 

class Test{

public:

~Test() { cout << "调用析构函数" << endl; }

};

 

void main()

{

Test *ptr=new Test[4];//分配4个对象长度的内存

delete ptr;//用delete释放该内存

}

在上例中用new分配了四个Test对象长度的对象数组,然后使用delete对指针ptr进行释放。最后的运行结果如图所示,本来四个对象应当进行四次析构,但是实际上只执行了一次析构。这是因为使用delete时,编译器默认其为单个对象,因此便只调用了一次析构函数,这样就造成了剩下的对象空间并未释放,造成了隐患。

  1. 总结

这是在学习C++中遇到的比较困惑的一个问题,这里写一个小的总结,使自己印象更深刻。不能够错误的使用delete和delete[],并且在使用之后记得对指针进行置空处理。

猜你喜欢

转载自blog.csdn.net/qq_23557345/article/details/81558180