内存四区之代码区,全局区,栈区和堆区

C++ 在程序执行时,将内存大致分为代码区,全局区,栈区和堆区四个区域。不同的区域存储不同的数据,赋予不同的生命周期,能够更灵活地进行编程。

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

下面通过一个例子对全局区,栈区,堆区的数据声明周期进行说明:

// 全局变量属于全局区,由操作系统管理释放
int g_a = 1;
int g_b = 2;
int main(void)
{
	cout << "g_a 的地址为:\t"<< int(&g_a) << endl;
	cout << "g_b 的地址为:\t" << int(&g_b) << endl;
	// 创建普通的局部变量,属于栈区
	int a = 10;
	int b = 20;	
	cout << "a 的地址为:\t" << int(&a) << endl;
	cout << "b 的地址为:\t" << int(&b) << endl;
	// 创建静态变量,属于全局区
	static int s_a = 40;
	static int s_b = 50;
	cout << "s_a 的地址为:\t" << int(&s_a) << endl;
	cout << "s_b 的地址为:\t" << int(&s_b) << endl;
	// 程序员自己创建变量,属于堆区
	int* d_a = new int(10);
	int* d_b = new int(20);
	cout << "d_a 的地址为:\t" << int(d_a) << endl;
	cout << "d_b 的地址为:\t" << int(d_b) << endl;
}

输出结果为:

g_a 的地址为:  5300224		g_b 的地址为:  5300228	
a 的地址为:    6421316		b 的地址为:    6421304
s_a 的地址为:  5300232		s_b 的地址为:  5300236
d_a 的地址为:  9547944		d_b 的地址为:  9547992

我们从中可以看到,g_ag_bs_as_b 都属于全局区,同理,ab 都属于栈区,d_ad_b 都属于堆区。由于栈区的数据在程序运行结束后会被编译器自动销毁,因此不要返回局部变量的地址,举例如下:

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

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

输出结果为:

a 的地址为:    7601480a 存放的数据为: 10
a 的地址为:    7601480a 存放的数据为: 2084553696

由于编译器会对栈区的数据做一次保留,因此第一条的 cout 语句能够正常输出,然而第二次的输出才是内存地址 a 中的数据。

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

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

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

输出结果为:

a 的地址为:    23507016a 存放的数据为:        10
a 的地址为:    23507016a 存放的数据为:        10

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...