内存中的栈与堆与静态存储区与代码区

一个程序,是存在硬盘上的。当你运行它时,需要将它拷贝入内存中才能运行。在内存中分别存放在栈区,堆区,静态存储区,代码区。
首先着重说明,不存在常量区(它在静态存储区内)或是文字常量区(Java或许有?),或是自由存储区(存在但是是抽象的)。

  1. 栈区存放局部变量,它处于内存中的高地址范围,每存入一个变量,就好似向栈中压入一个变量一样,即高地址向低地址生长。它的资源由编译器分配与释放,由于它在内存中是连续的,所以存释效率高
  2. 堆区存放局部变量,关键在于存放的是需要程序员手动分配与释放的变量,通过malloc/free©或者new/delete(C++)。这里后者其实存储在的是自由存储区,但free store是个抽象概念将其归入堆中不全对但也无大错(我可能会写一篇关于这个的文章)。堆区位于内存中的低地址区范围,像链表一样存入一个个malloc或者new的对象,即低地址向高地址生长,由于它在内存中可以不是连续的,所以存释效率低
  3. 静态存储区存放静态变量、全局变量与常量,它在内存中的位置位于堆下面。在C中静态存储区还分为初始化的和未初始化的区分别存放相应的变量(当然常量存放在初始化的区了)。在C++中没这种区分,直接就都存了。C++中这个区甚至可以存new出来的对象,所以说new出来的对象存在了自由存储区(自由嘛,自由选择存的位置)。new是通过重载构造函数来实现自由选择的。这也是和malloc的一个大区别之一,malloc不能重载。静态存储区中存放的数据初始化后将伴随程序走到最后,举个例子
#include <iostream>

using std::cout;
using std::endl;
int global = 1; //全局变量
static int sg = 2; // 静态全局变量
void func()
{
	static int funs = 3; //静态局部变量
	cout << funs << endl;
	funs++;
}
int main()
{
	cout << global<<endl; //1
	cout << sg << endl; //2
	func(); //3
	func(); //4
}

其实都不用举例子,很好懂,关键看funs, 正因为初始化后funs存入了静态存储区,调用第一次func()后funs不会像存入栈中一样被编译器释放,所以才会在第二次调用时输出4.
4.代码区存放代码,顾名思义嘛,但其实想想你写的代码,定义的变量都存在了栈区,手动new的都存在了堆区,静态的全局的常量的都存在了静态存储区,那还剩下什么?函数体。举个自己瞎编的经典例子

include <iostream>

using namespace std;
class A
{
public:
	void Hello()
	{
		cout << "Hello world" << endl;
	}
};
int main()
{
	A a;
	a.Hello();//Hello world
	A b;
	b.Hello();//Hello world
	cout<<sizeof(A); //1
}

这里的关键在于A的大小只有1。大家都知道类的大小不允许为空所以当类真是空时C++会象征性的给个char占位。也就是说函数Hello是不占任何空间的。为什么呢?就是因为它存在了代码区,它不属于实例,属于整个类。那为什么要把它存在代码区呢?你创建一个类的两个实例,这两个实例中的变量准定需要不同于彼此,他们自个的变量准定是自个的,不能共享(你所有变量都共享了不就还是同一个实例嘛,还整多个实例干啥)(想共享就static把它放静态区)。但它们的方法可以是共享的啊,而且必须做到共享,不共享的话每创建个实例,实例就得多占些空间(方法的空间),何苦来哉。

发布了26 篇原创文章 · 获赞 6 · 访问量 6464

猜你喜欢

转载自blog.csdn.net/weixin_43975128/article/details/98048514