代码区、全局区、堆区、栈区--内存四区

代码区、全局区、堆区、栈区–内存四区

秋招面试时有时会问到内存四区的相关问题,并且很多基础原理性的知识需要联系到内存四区来解释。自己总结一下:
根据数据类型的,划分为内存四区,带来了极大的便利,使大家能够更好的进行变成。

各区的特性

1、代码区:存放函数体的二进制代码,由操作系统管理和创建、代码区是共享的,对于频繁被执行的程序,只需要存有一份代码即可。
2、全局区:存放全局变量和静态变量以及常量,在程序结束后由操作系统释放。
3、栈区:由编译器自动分配释放,存放函数参数值和局部变量。函数运行完成后被系统释放。
4、堆区:一般由程序员通过new开辟空间,进行分配和释放,若程序员不释放,则程序结束时由操作系统回收。程序运行完成后释放。

代码说明

下面展示一些 内联代码片

// 全局变量属于全局区,由操作系统管理释放、存放全局变量和静态变量、常量
int  a= 1;
int  b= 2;
int main(void)
{
	cout << "a 的地址为:"<< int(&a) << endl;
	cout << "b 的地址为:" << int(&b) << endl;
	// 创建普通的局部变量,属于栈区
	int c = 10;
	int d = 20;	
	cout << "c 的地址为:" << int(&c) << endl;
	cout << "c 的地址为:" << int(&d) << endl;
	// 创建静态变量,属于全局区
	static int e = 40;  //
	static int f = 50;
	cout << "e 的地址为:" << int(&e) << endl;
	cout << "f 的地址为:" << int(&f) << endl;
	// 程序员自己创建变量,属于堆区
	int* g = new int(10);
	int* h = new int(20);
	cout << "g 的地址为:" << int(g) << endl;
	cout << "h 的地址为:" << int(h) << endl;
}

按照上面的解释:其中a、b为全局变量;e、f属于被static修饰的局部静态变量,所以属于全局区。c、d属于普通局部成员变量,属于栈区。g、h为程序员使用new开辟的新空间,属于堆区,可以手动释放,如果未手动释放,操作系统会在程序结束后释放。
由于栈区的数据在程序运行结束后会被编译器自动销毁,因此不要返回局部变量的地址,举例如下:
下面展示一些 内联代码片

int* func()
{
	int a = 10;	// 栈区数据,在程序执行完之后自动释放
	return &a;	//虽然返回了a的地址,然而数据在func结束时已经被销毁
}

int main(void)
{
	int* a = func();	// 此时a表示在函数func在栈区开辟的地址,但是其中的数据已被销毁
	cout << "a 的地址为:" << int(a) << "a 为:" << *a << endl;
	cout << "a 的地址为:" << int(a) << "a 为:" << *a << endl;
}

由于编译器会对栈区的数据做一次保留,因此第一条的 cout 语句能够正常输出,第二次输出为一个很奇怪的数。

相反,堆区数据由程序员自己进行管理,在程序执行完之后并不会自动释放。当整个程序执行完毕之后会由操作系统释放。

int* func()
{
	int * a = new int(10);	// 程序员使用new在堆区开辟空间,在程序执行完之后自动释放
	return a;	//同样返回了a的地址,然而只要程序没有运行结束,除非程序员释放,否则会一直保留
}

int main(void)
{
	int* a = func();	// 此时a表示在函数func在堆区开辟的地址,编译器无法自动销毁
	cout << "a 的地址为:" << int(a) << "a 为:" << *a << endl;
	cout << "a 的地址为:" << int(a) << "a 为:" << *a << endl;
}


版权声明:本文为weixin_50405454原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。