理解内存分区,对于C++的学习至关重要。分为代码区、全局区、栈区和堆区,下面一一简单讲解下。
代码区
编程语言基本上可以分为两类,编译型语言和解释型语言。
编译型语言
所谓编译型语言是指将代码编程为机器码,由CPU直接解释执行。C++就是编译型语言,根据不同的编译器(针对于CPU)编译成对应的机器码。
CPU体系结构
CPU根据体系结构的不同,也有许多种,最常见的就是intel的X86(32位)和X64(64位),ARM的armV7(32位)和arm64两大阵营。还有其它的例如mips、甚至很多国产芯片等等。
根据不同的编译器(CPU体系结构)会将C++代码编译成针对于不同体系结构的机器码。
解释性语言(了解即可)
将编译语言转换为中间码,或者直接通过解释器执行。
一般这样的语言都会提供相应的Runtime(运行环境),也就是虚拟机,所以执行效率肯定不如C++这种直接编译成机器码的效率高。
代码区的内存
既然代码编译成了机器码,那么程序运行的时候,自然要为这些代码开辟内存空间,方便CPU可以取指令(代码指令)解释执行。
兴趣
有兴趣的同学可以学习一下ELF文件,一般Window或者Linux变成的库或者可执行文件都是符合ELF规范的,ELF格式中有代码段,这些代码段就会映射到内存形成代码区。
全局区
全局区存放的是全局变量、静态变量和常量。
这些量可以发现它们的生命周期是伴随整个程序,也就是程序创建时它们就存在了,程序死亡时才会销毁。
全局变量
函数外定义的变量就是全局变量(如C语言中定义的函数外变量就是全局变量)。
静态变量
static关键字声明的变量
常量
程序中使用的常量,如:字符串、const修饰变量等。
兴趣
同样的是ELF文件中,也会有全局数据段,程序在加载内存时,会映射到全局区。
栈区
函数的参数和局部变量会存在栈区。
堆栈
堆栈的概念,相信很多工程师都是了然于胸的,LIFO(后进先出)。就好像箱子里放东西,最后放的肯定在最上面。
PC是一个寄存器,总是指向堆栈最后一个入栈地址。从示意图可以了解到,一个函数执行时,它的函数地址和形参都会入栈,函数中创建的局部变量也会入栈。当函数执行完,这些局部变量,形参和函数地址都会出栈。PC会指向堆栈中的函数地址下的地址,会是什么呢?(当然是调用这个函数返回的地方了)
注意
不会返回函数中的局部变量的地址,因为局部变量是栈区,随着函数的执行完就释放了。
int * getLocalVar() {
int a= 10;
//局部变量的地址是临时的
return &a;
}
堆区
需要申请堆区内存。
C语言malloc和free。
C++则是new和delete。
堆区的内存开辟需要自己手动的释放,这块内容没有什么好讲的。
程序中需要常驻内存的变量,那我们就需要使用堆区创建对象。