C++ free()运算符是否从动态变量中删除地址? 让我们考虑下面的程序: int main () { int *p, *r; p = (int*)malloc(sizeof(int)); cout<<"Addr of p = "<<p <<endl; cout<<"Value of p = "<<*p <<endl; free(p); cout<<"After free(p)"<<endl; r = (int*)malloc(sizeof(int)); cout<<"Addr of r = "<<r <<endl; cout<<"Value of r = "<<*r <<endl; *p = 100; cout<<"Value of p = "<<*p <<endl; cout<<"Value of r = "<<*r <<endl; return 0; }

C++ free()运算符是否从动态变量中删除地址? 让我们考虑下面的程序: int main () { int *p, *r; p = (int*)malloc(sizeof(int)); cout<<"Addr of p = "<<p <<endl; cout<<"Value of p = "<<*p <<endl; free(p); cout<<"After free(p)"<<endl; r = (int*)malloc(sizeof(int)); cout<<"Addr of r = "<<r <<endl; cout<<"Value of r = "<<*r <<endl; *p = 100; cout<<"Value of p = "<<*p <<endl; cout<<"Value of r = "<<*r <<endl; return 0; },c++,heap,dynamic-allocation,C++,Heap,Dynamic Allocation,在上面的代码中,p和r是动态创建的。 p被创建并释放r是在释放p后创建的。 更改p中的值时,r的值也会更改。但是我已经释放了p的内存,那么为什么在更改p的值时,r的值也会被修改为与p相同的值呢 我得出以下结论。请评论我是否正确 说明: 指针变量p和q是动态声明的。垃圾值最初存储。指针变量p被释放/删除。声明另一个指针变量r。分配给r的地址与p的地址相同(p仍然指向旧地址)。现在,如果修改了p的值,r的值也会被修改为与p的值相同的值(因为两个变量都指向相同的地址)。 运算符free()仅从指针变量

在上面的代码中,pr是动态创建的。 p被创建并释放r是在释放p后创建的。 更改p中的值时,r的值也会更改。但是我已经释放了p的内存,那么为什么在更改p的值时,r的值也会被修改为与p相同的值呢

我得出以下结论。请评论我是否正确

说明: 指针变量pq是动态声明的。垃圾值最初存储。指针变量p释放/删除。声明另一个指针变量r。分配给r的地址与p的地址相同(p仍然指向旧地址)。现在,如果修改了p的值,r的值也会被修改为与p的值相同的值(因为两个变量都指向相同的地址)。
运算符free()仅从指针变量中释放内存地址,并将地址返回操作系统以供重用,但指针变量(p在本例中)仍然指向相同的旧地址。

您对实际发生的情况的分析是正确的;但是,不能保证程序以这种方式可靠运行。每次在
free(p)
之后使用
p
“都会引发未定义的行为”。(当您访问
*p
*r
时也会发生这种情况,而您没有先在其中写入任何内容。)未定义的行为比产生不可预测的结果更糟糕,也比可能导致程序崩溃更糟糕,因为编译器被明确允许假设引发未定义行为的代码永远不会执行。例如,编译器将您的程序视为与

int main() {}
因为您的程序中没有不引发未定义行为的控制流路径,所以程序一定永远不会运行

free()函数和
delete
运算符不会更改指针的内容,因为指针是通过值传递的

但是,使用
free()
delete
后,指针指向的位置中的内容可能不可用

因此,如果我们有内存位置0x1000:

       +-----------------+  
0x1000 |                 |  
       | stuff in memory |  
       |                 |  
       +-----------------+  
让我们假设指针变量
p
包含0x1000,或指向内存位置0x1000

调用
free(p)
后,允许操作系统在0x1000处重用内存。它可能不会立即使用它,也可能会将内存分配给另一个进程、任务或程序


但是,变量
p
没有改变,因此它仍然指向内存区域。在这种情况下,变量
p
仍然有一个值,但您不应该取消引用(使用内存),因为您不再拥有内存。

您的分析在某些方面表面上接近,但不正确

p
r
被定义为
main()
的第一条语句中的指针。系统不会动态创建。它们被定义为带有
main()
的自动存储持续时间变量,因此当
main()

创建和释放的不是
p
malloc()
动态分配内存,如果分配成功,则返回一个指针,该指针标识动态分配的内存(如果动态分配失败,则返回一个
NULL
指针),但不初始化该内存。
malloc()
返回的值(在转换为指向
int
的指针后,这在C++中是必需的)分配给
p

然后,您的代码将打印
p
的值

(我已经用斜体突出显示了下一段,因为我将在下面再次提到它)

下一条语句打印
*p
的值。这样做意味着访问
p
指向的地址处的值。但是,该内存未初始化,因此访问
*p
的结果是未定义的行为。在您的实现(编译器和库)中,此时会产生一个“垃圾值”,然后将其打印出来。然而,这种行为并不能保证——它实际上可以做任何事情。不同的实现可能会产生不同的结果,例如异常终止(程序崩溃)、重新格式化硬盘驱动器,或者[在实践中不太可能]原语通过计算机的扬声器播放歌曲“崩溃”

调用
free(p)
后,您的代码将按照与指针
r
类似的顺序运行

赋值
*p=100
具有未定义的行为,因为
p
保存第一次
malloc()
调用返回的值,但该值已传递给
free()
。因此,就您的程序而言,内存不再保证存在

之后的第一个
cout
语句访问
*p
。由于
p
不再存在(已被传递到
free()
),这将导致未定义的行为

之后的第二个
cout
语句访问
*r
。该操作具有未定义的行为,原因与我在上面斜体段落中描述的完全相同(对于
p
,当时是这样)

但是,请注意,代码中出现了五次未定义的行为。即使是一个未定义的实例
       +-----------------+  
0x1000 |                 |  
       | stuff in memory |  
       |                 |  
       +-----------------+  
#include <iostream>
#include <cstdlib>

using namespace std;