交代一下背景,最近一直在看C++的相关知识,今天刚好看到“引用”这一部分。于是好奇心驱使,我想知道它与java的引用到底有什么不同,于是开始搜索大法,java的引用更加与c++的指针更加类似,但是也不一样,当然这不是重点。然后搜索的时候,突然又想知道在内存中的存储情况,于是开始搜索……,搜索……。对于heap与stack的区别我又模糊了,于是到了今天的重点,顺便记录一下自己搜索的成果。
英文好的同学可以直接看
https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
和http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/、https://www.youtube.com/watch?v=450maTzSIvA
特别是上面的这个视频解释的特别生动形象,建议大家都看一下。
我这里主要也是引用别人的文章,还请各位勿怪。
堆和栈在什么位置?
答:他们都存在计算机的RAM中,如果想进一步知道虚拟内存的可以移步这里 How Virtual Memory Works,还有这个视频(推荐,讲解的很清楚)https://www.youtube.com/watch?v=qlH4-oHnBb8
在线程中是如何与堆、栈进行交互?在多线程中,堆与栈又是怎么样一个机制?
答:在一个多线程并发的应用中,每个线程都有自己的栈。但是所有不同的线程共享一个堆,由于不同的线程共享一个堆,必然导致不同的线程之间存在协调关系,不同的线程在同一时间不会访问相同的内存地址。
对象可以保存在栈上吗?
答:可以,一个对象可以被保存在栈中,如果你在一个方法函数中没有通过new关键字创建一个对象,那么这个对象就会被存在栈中。示例代码(c++)如下:
void somefunction( )
{
/* create an object "m" of class Member
this will be put on the stack since the
"new" keyword is not used, and we are
creating the object inside a function
*/
Member m;
} //the object "m" is destroyed once the function ends
一旦方法执行完毕,对象“m”就会从栈中移除。
再看一段代码
void somefunction( )
{
/* create an object "m" of class Member
this will be put on the heap since the
"new" keyword is used, and we are
creating the object inside a function
*/
Member* m = new Member( ) ;
/* the object "m" must be deleted
otherwise a memory leak occurs
*/
delete m;
}
以上对象是通过new 关键字创建的,因此这个对象存在内存堆中。在c++中需要我们手动移除,否则会造成内存泄漏
栈的大小可以增大吗?堆的内存大小可以增大吗?
答:栈的内存大小是一个固定值,不能增加(部分语言可以)。因此,如果栈的内存没有足够空间的时候,就会出现stack overflow,经常出现在很多嵌套方法使用的时候,或者是存在一个死循环。
而堆的内存可以通过系统机制调大,这是一点很重要的区别
堆与栈哪个速度更快?
栈的读写速度更快,因为分配内存的机制,只是移动指针,而堆还要做查找等操作。
下面附上一张图说明堆和栈的关系,图片来源于https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap
还有更加形象的图,用于说明为啥栈比堆要快:同样来源于上面的网址
栈
堆
一团乱糟糟的heap与整齐的stack,自然没法比。
关于java的示例
其他常见问题(持续更新)
- 全局变量也是放在栈里吗?
答案:否,放在堆里 - 静态变量、常量存放在哪里?
答案:还有一个内存区域叫做方法区