删除指针

5
我希望问一下,动态创建一个指针,然后将指针地址改变为其他值,是否仍会删除原始分配的空间?
例如:
int main()
{

int c = 50;
    // Memory leak
    int * q = new int;
    q = & c;
    delete q;
}

“到底是什么被删除或发生了什么?”感谢您的提问!

1
请注意,在上述代码中您正在动态创建的是一个int,而不是指针。指针本身位于堆栈上,并且它被设置为指向您从堆中分配的int。 - Jeremy Friesner
5个回答

8
“究竟会发生什么,或者说会被删除什么?” 这将导致内存泄漏和未定义行为。 当您执行q = &c;时,您就失去了对由new int分配的内存的唯一跟踪。没有人为您跟踪这个过程,也没有垃圾回收器,它只是丢失了,无法恢复。当您执行delete q;(其中q被分配给&c)时,您正在删除您没有分配的内存,更糟糕的是,您正在删除堆栈上的内存。任何一种情况都会导致未定义行为


这是一个很好的前置知识,让您避免在不需要使用指针的情况下使用它们。在这种情况下,没有理由动态地分配您的int。如果您确实需要指针,请使用c++11智能指针(如果没有c++11,则使用boost)。越来越少的情况需要真正需要一个原始c类型的指针。您应该阅读Effective Modern c ++第4章,以获取有关此主题的优秀详细信息。

5

动态创建指针,然后将指针地址更改为其他地址,是否仍会删除原始分配的空间?

不会。 delete 将释放其操作数指向的内存。您必须从 new 获得相同的内存块并进行 delete

int c = 50;
int * q = new int;
int * r = q;
q = & c;
delete q;     // WRONG! q points to something you didn't get from new
delete r;     // OK! p points to the block you got from new

为了更加清晰,delete并不关心它所操作的变量是什么,它只关心该变量指向的内容。在上面的最后一行中,r 指向最初由 q 指向并由 new 分配的块,因此您可以安全地使用 delete。而 q 指向静态分配的内存,而不是从 new 获取的内容,因此不能使用 delete
但是,您可以将所需值复制到 q 指向的空间中,而无需更改 q 的指向。
int c = 50;
int * q = new int;
*q = c;
delete q;     // OK! q still points to the same place

在这里,您正在更改q指向的位置中存储的值,但您没有更改q本身。 q仍然指向从new获取的块,因此可以安全地使用delete


4
您的代码将尝试删除c。在C/C++中没有内存管理或其他类似机制。delete将尝试删除给定指针指向的任何内容,并且未被删除的任何内容(通过调用new创建的变量调用delete,或者通过离开本地变量的作用域)将保留在内存中,直到程序结束。
请注意,尝试删除本地变量可能会导致崩溃,因为delete实际上会检查它要删除的内容(以一种非常基本的方式),至少要知道在该地址分配了多少内存。在此检查中,它可能会注意到c不包括此信息,或者它甚至不在内存空间的正确端点,因此它将崩溃。

2

程序会崩溃,因为c被创建在堆栈内存区域。如果你很幸运,程序没有崩溃,但是还是存在内存泄漏,因为q的引用已经丢失。


2
如果它不崩溃,你就不会幸运。很可能只有在你集成了这段代码并且它已经在客户端站点上使用很久之后才会崩溃。我认为最好的结果是立即崩溃。 - Fantastic Mr Fox

2

首先回答你的问题:

我想问一下,动态创建指针是什么意思?

我们不会动态创建指针。在C和C++中,指针就像其他变量一样。不同之处在于,指针是一种可以存储特定内存位置地址的变量。在运行时,您只需动态分配内存并将该内存大小的第一个地址位置的地址分配给它即可。

如果您不删除/释放内存并为其分配新地址,会发生什么情况?在这种情况下,内存将不会被释放/释放,并且操作系统永远不会将其标记为空闲。当您释放/删除内存时,操作系统将该区域标记为空闲状态,您的运行进程可以在未来利用它。这就是适当的内存管理。不适当的内存管理会导致程序出现内存泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接