销毁局部变量是什么意思。
void f()
{
int x=10;
}
当该函数调用时,函数结束时,局部变量就会被销毁 x
会是什么?
而对于。
void f2()
{
int a=100;
int* b=&a;
}
结束 f2()
该局部变量是什么 b
'的价值?将 b
指针是一个悬空指针(有地址但没有任何值)?
当该函数调用时,函数结束时那个局部变量x会是什么?
不存在。 蒸发了。 蒸发了。 消失了。
x
这里是一个具有自动寿命的变量。 "自动 "指的是,当 x
出了范围,就会被销毁。 (不完全是 删除,因为该词意味着调用 delete
)
所有的自动变量也是如此,不管它们是积分、字符串、浮点数,甚至是指针。
void f2()
{
int a=100;
int* b=&a;
}
在这里... a
和 b
是自动变量。 它们都会在它们的作用域结束时被销毁--即在 f2()
. 然而,所有被销毁的都是变量本身。 如果一个自动变量是一个指针(例如,一个 原始 指针),那么 指针指向的东西 会 不 被摧毁。 考虑到。
void f3()
{
char* p = new char [256];
}
p
这里仍然是一个自动变量,类型为指针到查尔。 这个东西 p
指向不是自动的 -- 那是动态分配的(我们使用了 new
).
如上所述。p
会被销毁,但它所指向的内存不会。 这就是内存泄漏。 为了解决这个问题,你必须 delete
它。
void f3()
{
char* p = new char [256];
delete [] p;
}
现在,记忆指的是... p
已被正确销毁,而指针本身 (p
)将在其范围结束时被销毁,因为它是一个自动的。
的寿命。p
和什么 p
指的是没有任何联系的。 就因为你 delete
p
并不意味着 p
本身 现在也被销毁了。 p
仍然是一个自动变量。
一个例子。
void f3()
{
char* p = new char [256];
cout << (void*) p << "\n"
delete [] p;
// p still exists, it just points to to nothing useable
cout << (void*) p << "\n"
}
After the delete
的值,我们打印出 p
到屏幕上。 如果你运行这个程序,你会看到 p
与删除前相比并没有变化。 p
本身不受 delete [] p;
. 但在 f3()
的收尾支架 }
,它将从作用域中掉出来,并在那里被销毁。
b
不会是一个悬空的指针,因为你没有在堆上分配任何内存(使用了 malloc
或 new
它只是一个指向本地变量的地址的指针。a
(当你退出函数的作用域时就会被销毁)一旦该函数的堆栈框架被弹出......你就不能再引用那些局部变量。
当 f()
出口。x
将不复存在。从技术上讲,用于它的内存当然还在,但编译系统可以自由地将该内存空间用于任何它喜欢的事情。而且它最终会把它重新用于完全不同的东西。
如果你把 x
并将其从函数中传出,取消引用该指针是最糟糕的未定义行为。例子:
int* f() {
int a;
return &a;
}
int main() {
int* pointer = f();
//int b = *pointer; //Undefined behaviour, the compiler could choose to format your harddrive now!
}
变量 x
, a
和 b
都是局部变量,所以它们在函数返回后就不存在了。如果你试图询问其中任何一个变量的值是什么,调试器可能会说 "找不到 x
在这种情况下"。
更详细地说,这些变量的内存是从堆栈中分配的,并在函数返回时返回到堆栈中。调用 f()
本质上是将值10放在堆栈的顶部;如果你再创建另一个 int
在堆栈上未初始化,它可能会从10开始(你不应该依赖这种行为,因为它没有保证,但它给了你一个关于堆栈在许多系统上如何工作的基本概念)。
你并没有破坏任何东西,你的变量超出了范围。
因为它不是堆分配的,所以你不会有任何内存管理方面的问题。
如果你真的想了解这样的机制,你可以下载ollydbg(假设是windows),然后在执行这个函数之前、期间和之后进入,以便了解现代编程语言& 编译器如何处理局部变量。
指针本身也会超出范围。指针 f2
会在函数结束时被销毁,在这种情况下不会造成内存泄漏,因为它指向的对象是在堆栈上,而不是用 new
.
但如果考虑到以下情况。
int *global;
void foo()
{
int a = 10;
global = &a;
}
那么指针 global
存在后 foo
已完成运行,但指向一个已销毁的范围外变量,该变量的值未被定义。