栈和堆之间的区别经常会让很多人困惑。所以这里列举了一些关于堆栈的问题和解答,以此帮助大家理解堆和栈。
栈和堆分别储存在哪里?
它们都储存在计算机的RAM(随机存储器)中。作为对RAM和虚拟内存的回顾,可以读一下这篇文章:这里。
线程是如何影响栈和堆的?在多线程中,栈和堆是怎样工作的?
在多线程应用中,每一个线程都有一个自己的栈。但是不同的线程可以共享一个堆。因为多线程应用中,不同的线程会共享同一个堆,所以这就意味着必须要处理好线程之间的协同性,使它们不会同时访问同一块内存。
对象可以储存在栈中,而不储存在堆中吗?
可以,一个对象可以储存在栈中。如果函数中不使用new
创建一个对象,这样这个对象就会储存在栈中,而不是堆中。假设我们有一个叫做Member的C++类,用来创建对象。同时有一个somefuction()
函数。代码看起来应该是这样的:
在栈中创建对象
void somefuction()
{
/*创建一个名叫m的Member类对象,
当没有使用new时,将会储存在栈中,
这样就在函数中创建了一个对象
*/
Member m;
} //对象m会在函数结束后被销毁
所以,在函数执行完成后,m对象就会被销毁,或者可以说它超出了作用域。对象m使用的内存会在函数运行结束后被移除。
如果想要在函数中创建一个储存在堆中的对象,这种情况下应该这样写:
在堆中创建对象
void somefunction()
{
/* 由于使用了new,创建Member类的对象时,
会储存在堆中,这样就在函数中创建了一
个对象
*/
Member* m = new Member();
/* 对象m必须销毁,否则会出现
内存泄漏
*/
delete m;
}
在上面的代码中,可以看到在函数中使用了new
来创建了m对象。这就意味着m会在堆中创建。但是正义如此,同样也意味着我们必须自己删除它,否则就会出现内存泄漏的错误。
栈和堆中的内存分别会持续多久?
一旦函数完成,栈中关于这个函数的数据就会自动被删除。任何在堆中的数据一直到程序员手动删除之前一直会存在。
栈可以增加规模吗?堆可以增加规模吗?
栈是固定大小的,不能够增加它的固定大小(然而,有些编程语言进行了扩展,使其可以改变大小)。所以如果栈中没有足够大的空间来处理分配给它的内存,就会出现栈溢出的情况。这经常会在多层嵌套或者无线循环的函数中出现。
而如果堆现在的空间不足以容纳新的内存,那么系统就会分配给它一些新的内存。这是栈和堆之间的一个很大的不同。
栈和堆是怎样实现的?
具体实现要看编程语言,编译器和运行环境——使用不同的编程语言和编译器时,堆栈的实现有很多小的细节方面的不同。但是总的来说,堆栈在一种编程语言中要完成的事情和在另一种编程语言中是相同的。
栈和堆哪个更快些?为什么?
栈要比堆快很多。因为内存就是以栈的形式分配的。分配内存到栈仅仅就是给栈加个标签一样简单。
栈和堆中的内存是怎样释放的?
在变量超出作用域之后,栈上的数据就会自动被释放。但是在有些语言,像C和C++中,储存在堆中的数据必须要通过使用像free,delete,delete[]
这样的关键词来删除。其它的一些语言像Java和.NET中,使用垃圾回收机制自动的将内存从堆中删除,而不需要程序员做任何事。
栈和堆分别会出现哪些错误?
如果栈中内存用尽,就会出现内存溢出错误,这会使程序崩溃。堆会出现碎片化的问题,这是由于堆中使用的可用的内存储存在分块,不连续的块中,因为使用了的内存会在未使用的内存块之间。当出现过多的碎片时,可能导致无法分配新内存。由于这个事实,尽管有足够的内存分配给需求,但是可能没有足够大的整块内存分配给需求。
应该使用哪一个?栈还是堆?
对于刚刚开始编程的人来说,建议使用栈,因为它比较简单。由于栈比较小,所以当你在知道自己确切需求多少内存,或者知道数据规模很小时,可以使用栈。在你需要使用的内存很大或者不知道确切的大小(就像动态数组一样)时,建议使用堆。
原文:via
by balzc:在Java,数组和对象的引用,以及基本变量的储存都是储存在栈中的,而new产生的数组和对象则储存在堆中,程序是通过引用找到它们的。