前言
delete 用于释放动态申请的内存。
- 传递给delete的指针必须指向动态分配的内存,或者是一个空指针。
- delete一块并非new的内存,或将相同的指针值释放多次,其行为是未定义的。
- 编译器不能分辨一个指针所指向的对象是静态还是动态分配的。
- 编译器也不能分辨一个指针所指向的内存是否已经释放。
延伸
delete一个已经delete的指针,为什么有时候会报错有时候不会?一个指针delete后是什么状态?
reference1:使用delete删除指针(转) - romanten - 博客园 (cnblogs.com)
这篇文章说delete后成了野指针,在内存里乱指一通,它作为地址的值还是有效的,还可以访问它以前指向的内存,不过那片内存被重新格式化了;此时如果误用p指针,仍然可以修改内存的值和从该处取出数值,但此时数据不受保护,该内存空间可能被重新被分配给别的变量。
通过实践后发现delete后的指针并没有指向一个随机的地址,要么是指向之前的地址,要么是指向了00008123这个地址,所以它不是一个野指针,如下所述:
结论
从我个人的理解来看delete过后指针是变成了一个悬空指针,因为从野指针的定义上,”野指针“是未被初始化的指针并且指向的位置是不可知的,而“悬空指针”是指向一块曾经保存数据对象但现在已经无效的内存的指针,它的地址依然是指向之前所指向的地址,只是该内存空间被释放且不能再使用,若使用解引用操作会直接报错,更符合delete之后的情况。但是通过实验发现一个问题,delete一个局部变量的指针后会将地址值变为00008123,而delete一个成员变量则是正常的指向之前的值。
问题
#include <iostream>
using namespace std;
class Test {
public:
Test(int _number) {
p = new int(_number);
}
~Test() {
cout << "address: " << p << endl;
delete p;
cout << "after delete address: " << p << endl;
}
public:
int *p;
};
void try1() {
Test t1(120);
}
void try2() {
int* q = new int(120);
cout << "address: " << q << endl;
delete q;
cout << "after delete address: " << q << endl;
}
int main()
{
try1();
try2();
return 0;
}
输出如下:
address: 0106D078
after delete address: 0106D078
address: 0106D078
after delete address: 00008123
这个问题可能是VS的编译器导致的,目前还不知道原因是什么。
可参考的因素:可能是为了方便及早发现已经释放的内存,而将这个无效值:00008123直接插入到delete语句。如果使用以下的操作可以阻止普通函数修改指针。
delete (int*) p; //传右值的操作
delete (p = p); //有副作用的赋值
int * volatile p; //重新赋值
delete q; //成员变量
使用注意:
我们需要注意的是在将指针delete过后,将其赋值为空。即 p = nullptr。或者使用智能指针shared_ptr来代替new和delete申请动态内存的操作。
reference2:野(wild)指针与悬空(dangling)指针 - veli - 博客园 (cnblogs.com)