C++ 中 delete 指针后发生了什么(动态内存分配)
总结:
形如 int *p= new int(1),delete p 后,p 指向的地址所存目标被删除,该目标所占的堆空间也被删除,但是指针 p 本身没有被删除
三个关键点值得注意:
- 指针自身的地址
- 指针指向的地址
- 指针指向的地址所存的目标
int *p = new int(1); // 动态内存分配
int *p2 = p;
cout << "val of p (address pointed by p): " << p << endl;
cout << "val pointed by p: " << *p << endl;
cout << "address of p: " << &p << endl;
cout << "val of p2 (address pointed by p2): " << p2 << endl;
cout << "val pointed by p2: " << *p2 << endl;
cout << "address of p2: " << &p2 << endl;
cout << "delete p" << endl;
delete p; //删除了p指向的目标,并且释放了该目标所占的堆空间
cout << "val of p (address pointed by p): " << p << endl; // p 现在是野指针,p所指向的地址是随机的
//cout << "val pointed by p: " << *p << endl; //p 现在是野指针,p所指向的地址不一定被分配了内存,即目标不一定存在,所以该语句可能会报错
cout << "address of p: " << &p << endl; // p 的本身没有被删除,所以自身的地址没有改变
cout << "val of p2 (address pointed by p2): " << p2 << endl; // p2 所指向的地址并未发生改变
cout << "val pointed by p2: " << *p2 << endl;//但是该地址所存目标已经被删除,所以该地址所存值是一个无效值
cout << "address of p2: " << &p2 << endl; //p2 自身的地址没有改变
运行结果如下:
val of p (address pointed by p): 008D5560
val pointed by p: 1
address of p: 006FF84C
val of p2 (address pointed by p2): 008D5560
val pointed by p2: 1
address of p2: 006FF840
delete p
val of p (address pointed by p): 00008123
address of p: 006FF84C
val of p2 (address pointed by p2): 008D5560
val pointed by p2: -572662307
address of p2: 006FF840
指针作为函数参数,指针指向无法改变
总结:
当指针作为函数参数时,传入函数的指针实际上是原指针的拷贝
- 当对指针指向的值进行修改时,原指针指向的值也发生对应修改
- 但当对指针指向(即指针的值)进行修改时,原指针指向不会发生改变
为了能够对原指针指向进行修改,应该将原指针的引用作为参数传入,此时函数中对指针的任意操作都是直接对原指针进行操作
- 当对指针指向的值进行修改时,原指针指向的值也发生对应修改
- 但当对指针指向(即指针的值)进行修改时,原指针指向发对应生改变
//指针
void fun1(int *p) {
cout << "address of p in fun1: " << &p << endl;
*p = 5;
p = nullptr;
}
//指针的引用
void fun2(int*& p) {
cout << "address of p in fun2: " << &p << endl;
*p = 1;
p = nullptr;
}
void main(){
int tmp = 10;
int *p = &tmp;
cout << "initial: address of p is: " << &p << endl;
cout << "initial: the val of p is: " << p << endl;
cout << "initial: the val pointed by p is: " << *p << endl;
fun1(p);
cout << "after fun1(p): the val of p is: " << p << endl;
cout << "after fun1(p): the val pointed by p is: " << *p << endl;
//记录p的指向
int *p_tmp = p;
fun2(p);
cout << "after fun2(p): the val of p is: " << p << endl;
cout << "after fun2(p): the val pointed by p_tmp is: " << *p_tmp << endl;
}
运行结果如下:
initial: address of p is: 00C1FD40
initial: the val of p is: 00C1FD4C
initial: the val pointed by p is: 10
address of p in fun1: 00C1FC54
after fun1(p): the val of p is: 00C1FD4C
after fun1(p): the val pointed by p is: 5
address of p in fun2: 00C1FD40
after fun2(p): the val of p is: 00000000
after fun2(p): the val pointed by p_tmp is: 1
指针赋值的含义
总结:
有 int a, int *p , int *p2, p=p2 表示将p2的指向赋值给p, p=&a 表示将a的地址赋值给p
class ListNode {
public:
ListNode(int _val) :val(_val),next(nullptr) {};
int val;
ListNode* next;
};
void main(){
int aa = 1;
int bb = 2;
int *p = &aa;
int *p2 = &bb;
p = p2; //将p2的指向赋值给p,此时p也指向bb,但是p本身的地址不会改变
p2 = &aa; //将aa的地址赋值给p2,此时p2指向aa,但是p2本身的地址不会改变
ListNode L1(1);
ListNode L2(2);
ListNode L3(3);
cout << "address of L1: " << &L1 << endl;
cout << "address of L2: " << &L2 << endl;
cout << "address of L3: " << &L3 << endl;
ListNode *pre = &L1;
ListNode *cur = &L2;
cout << "address of pre: " << &pre << endl;
pre->next = &L2;
cout << "pre->next = &L2" << endl;
cout << "address of pre: " << &pre << endl;
pre = cur;// 将cur的指向赋值给pre, 本质上是指针pre从L1地址移动到了L2的地址,pre本身地址没有改变
cout << "pre = cur" << endl;
cout << "address of pre " << &pre << endl;
cout << "val of pre: " << pre << endl;
cout << "cur = &L3" << endl;
cur = &L3;//将L3地址赋给cur,此时cur指向L3,但是pre仍然指向L2,
cout << "val of pre: " << pre << endl;
cout << "val of cur: " << cur << endl;
}
address of L1: 012FFD14
address of L2: 012FFD04
address of L3: 012FFCF4
address of pre: 012FFCE8
pre->next = &L2
address of pre: 012FFCE8
pre = cur
address of pre 012FFCE8
val of pre: 012FFD04
cur = &L3
val of pre: 012FFD04
val of cur: 012FFCF4
参考文献:
- https://blog.csdn.net/ai_yue/article/details/80769243