网站首页 > java教程 正文
很多时候,你会被问到,也许是在面试的时候,堆和栈有什么区别?什么时候变量被分配到堆中?什么时候被分配到栈中?不是提问者故意刁难,也不是这样问,就显得自己有多么高大上。作为一个码农,不知道答案也许没关系,但这样一来,你也就未必真的了解自己的代码。
堆和栈,都是机器的一块内存区域。区别是,两者的用途和访问速度都不一样。栈直接参与系统调用,作为存放临时数据的地方,它的地址是放在专门的寄存器中的。这些寄存器,就是CPU直接访问的地方。这样一来,栈存取速度特别快,但能支持的数据类型,就非常有限,仅限于整数,指针,浮点数等系统直接支持的数据类型。涉及到函数调用的时候,系统先把函数返回地址入栈,然后依次放入函数局部变量。执行完后依次出栈,最后是函数返回地址。这种方式,直接决定了函数局部变量的生命周期。
相对于栈来说,堆要大得多。它是C++编译器定义的内存区域,通过编译器来访问。这块区域,就是给程序动态分配内存用的。当编译器看到new关键字调用的时候,它会去堆中尝试分配指定大小的内存区域,如果成功,就返回内存块的首地址;如果失败,则返回NULL。这块内存在程序运行时是不会被系统自动释放的,需显式调用delete来释放。
另外,C++编译器还定义全局区以存放全局或者静态变量。它还定义常量区以存放常量。
了解这些,你就会明白,把栈变量的地址返回给指针没有任何意义,而程序的输出结果也会出乎你的意料。当你使用new关键字创建对象的时候,返回值必定是个地址。过多使用new分配内存,会导致内存碎片和程序效率降低。在函数体体定义int i=0,i会放到栈中;而在函数体外定义,它会被放到全局区(注:类定义中初始化变量是不允许的);如果是在函数内部定义int *i = new int,i又会被放到堆中,这个时候,i代表的内存块是不是被清除的,尽管在退出函数的情况下。
下面是一个例子,用来说明C++针对不同变量的内存分配情况。
#include <iostream>
using namespace std;
int g;
class myclass{
int i;
double d;
long l;
int arri[2];
public:
void f(string className){
int a = 0;
cout << "address of function variable from " << className <<".f a:" << (long)&a << endl;
}
};
int main(){
myclass b,c;
cout << "size of b:" <<sizeof(b) << endl;
cout << "address of b:" << (long)&b << endl;
cout << "size of c:" <<sizeof(c) << endl;
cout << "address of c:" << (long)&c << endl;
myclass *d = new myclass;
cout << "size of d:" <<sizeof(*d) << endl;
cout << "address of d:" << (long)d << endl;
b.f("b");
c.f("c");
cout << "address of global variable g:" << (long)&g << endl;
}
执行后输出结果是:
这里,类变量b,c以及函数f里的int变量a,都是局部变量,放在栈中。其中,b和c的地址是连续的,正好相差32个字节。类变量d通过new关键字分配内存,所以它的起始地址就跟b和c不一样(我的环境里是25769945744),虽然也是局部变量,但是是放在堆中的。这里注意,两个局部变量a的地址是完全一样,虽然是通过不同的函数调用来定义。这也正好体现了栈的特点:栈自动分配和释放内存;栈内存可迅速重用。
- 上一篇: 还有多少人搞不懂堆内存和栈内存的区别?
- 下一篇: 达内java培训专家:如何理解Java堆栈?
猜你喜欢
- 2025-08-03 JVM内存结构和Java内存模型
- 2025-08-03 C++ 知识小结
- 2025-08-03 Java内存模型(JMM)详解
- 2025-08-03 为什么计算机内存需要堆和栈?
- 2025-08-03 Java中,对象一定在堆中分配吗?
- 2025-08-03 看完这篇,还不懂JAVA内存模型(JMM)算我输
- 2025-08-03 别再混淆了!JVM内存模型和Java内存模型的本质区别
- 2025-08-03 【C语言】(13)堆和栈
- 2025-08-03 达内java培训专家:如何理解Java堆栈?
- 2025-08-03 还有多少人搞不懂堆内存和栈内存的区别?
你 发表评论:
欢迎- 08-03JVM内存结构和Java内存模型
- 08-03C++ 知识小结
- 08-03Java内存模型(JMM)详解
- 08-03为什么计算机内存需要堆和栈?
- 08-03Java中,对象一定在堆中分配吗?
- 08-03看完这篇,还不懂JAVA内存模型(JMM)算我输
- 08-03别再混淆了!JVM内存模型和Java内存模型的本质区别
- 08-03【C语言】(13)堆和栈
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)