java和C++程序data存储的位置都分为以下五种:
1.寄存器(Registers):
最快的存储介质,就位于cpu中.
如果你用java,你不用直接跟它打交道或者说系统会帮你安排。
但是在C++中你可以为变量加上一个关键字:register, 表示这个变量经常使用,推荐compiler把这个变量放进去cpu的寄存器中,但是最终到底在不在registers中呢,It depends。还要考虑一下因素:
(1)寄存器还够不够用呢
(2)该变量是否后面使用了'&'取址符
等等。
2.栈(The stack)
栈位于RAM中!速度稍慢于寄存器。
java:存放基本类型的数据和对象的引用,但对象(非基本类型)本身不存放在栈中,而是存放在堆中。
c++:对于C++来说也差不多,存放着局部变量(基本类型和指针)等。
stack存放的都是临时的对象:
(1)Automatic variables 自动变量即是局部变量
(2)function arguments函数参数
(3)return values函数返回值
等等
这里详细介绍一下函数的压栈出栈操作:
当一个函数被调用的时候:
(1)先将下一条指令压栈,以便当函数执行完之后cpu可以执行该函数调用的下一条指令
(2)在栈上面申请空间预留给函数调用的返回值,保存返回值要用到
(3)cpu跳到函数的代码段
(4)这时有一个特殊的指针栈帧(stack frame)指向栈的最上面,后面压栈进来的所有东东都会被认为是该函数的局部数据(local)
(5)函数参数进栈
(6)函数主体的指令执行
(7)局部变量进栈
当函数执行完毕后:
(1)函数的返回值会被复制到刚刚开始被调用的时候就申请的空间(当然在栈内)中
(2)在栈帧后面的所有东西都会被销毁,就是局部变量和函数参数都会被销毁掉
(3)函数的返回值被销毁
(4)cpu读取之前保存下来的该函数调用的下一条指令并执行。
具体请参考:
http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
注:栈帧(stack frame)请参考:《深入理解计算机系统》:chapter 3:Machine-Level Representation of Programs: 3.7 Procedures
3.堆(The heap)
位于RAM中,速度比stack慢点
多用于申请占用内存比较大块的数据
java:使用new,只管申请使用可以了,不用手动去释放内存。
c++:new 或者 malloc,因为C++以效率为重,所以heap的使用还是手动的。
关于stack和heap的讨论:
(1).生命周期:
如果变量存放在stack中,这是由编译器来决定该变量的生存时间,而且可以自动销毁。但是如果变量是在heap中创建的话,在C++中,要手动的
通过new,delete来创建和销毁。在java中,手动的new,但是不用手动销毁,因为java有garbage collector。gc可以智能销毁。
(2).栈是在内存中是连续的,而且遵守简单的原则:就不断的push/pop。因为速度比较快,而且管理起来比heap简单。
heap是相对而言比较复杂,heap允许自由的申请和销毁内存空间,容易导致内存碎片。
(3).stack空间有限,如果在stack中申请的内存过大,容易发生stack overflow.
4.常量池(Constant storage)
常量设计的本意就是代表某个值而不再改变。实际上常量保存的地方不仅仅于ROM,包括:(1)真的就放在ROM(2)只读权限的RAM(3)在机器指令里面
常量可以保存在ROM里面,但是我们不能说常量就在ROM里面。因而个人认为我们对于常量池这个术语要灵活一些。
5.非RAM存储(Non-RAM storage)
这个已经跟内存已经没有关系了,但是还是提及一下。如果数据跟程序可以完全脱离,如:streamed objects 和 persistent objects,即使程序没有跑,它还是可以独立存在的。
当需要的时候还可以载入内存中。java提供了轻量级的持久化对象和机制:JDBC 和 Hibernate。
转载请注明出处。