C++中的堆区和栈区以及static和const

一、五大区       

         在C++中,内存分成5个区,他们分别是堆、栈、自由存储区(代码区)、全局/静态存储区和常量存储区。

栈区: 存放函数的参数值局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限,一般栈区的小于是10M。栈区是向低地址扩展的,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,大小在进程分配时是确定的,具体大小看编译器,操作系统。

        拿常见的2M举例,一个int是4个字节,2M的大小就是2M=2*1024K = 2 * 1024*1024 B,这么多个字节。 栈里面的地址是向低地址扩展的,可以想象成从栈底向栈顶消耗栈空间。在栈里面分配空间的优点是:分配速度快,不用担心用完了回收的事情。缺点就是:整个栈的空间大小太小了,拿2M的大小来算,就能放int类型的数据2 * 1024*1024 / 4 = 524288个,所以栈的地方很适合函数局部变量,不必担心回收的问题,不适合申请很大的空间。


堆区:堆区的申请是动态的,可通过用户传入的参数申请指定长度的内存空间,堆的内存也是很大,可以看成当前后台空闲的内存大小,可以通过new,malloc,calloc,realloc申请,回收的方式是delete或者free。堆区的地址是从低向高扩展的。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。

全局/静态存储区: 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。

 由图中可见,x和a分别为初始化过的全局变量和静态变量,再看存储地址都放在同一区域,而未初始化全局和静态存放在一片区域。

常量区:常量存储在这里,不允许修改。比如用const修饰的变量,其值就不可修改。

代码区:顾名思义,存放代码。

堆和栈的区别:

参考: 堆和栈的区别

(1)管理方式不同。栈由操作系统自动分配释放,无需手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小;

(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低

(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需手动实现。

(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持,所以栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多;

(6)存放内容不同存放的内容,是函数返回地址、相关参数、局部变量和寄存器内容等。一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

二、 static和const

参考:const与static的区别_Polymer to C++的博客-CSDN博客_const和static区别

        const就是只读的意思,只在声明中使用,意即其所修饰的对象为常量,它不能被修改,并存放在常量区。
        static一般有两个作用,规定作用域和存储方式(静态存储)。对于局部变量,static规定其为静态存储方式每次调用的初始值为上一次调用后的值,调用结束后存储空间不释放;对于全局变量,如果以文件划分作用域的话,此变量只在当前文件可见,对于static函数也是如此。static修饰的变量如果没有初始化,则默认为0.

        const和static修饰的全局变量如果要在多个文件之间共享,则可以在其他文件需要时使用extern关键字,声明外部变量,使用时一定包含所定义变量所在的文件

static

const
修饰局部变量static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束const修饰的局部变量为只读,其值不可修改。如果在程序中企图对const修饰的变量进行修改,那么程序就会报错
修饰全局变量一个全局变量被static修饰,存储在静态存储区,在整个程序运行期间一直存在,并且这个全局变量只能在本源文件内使用,不能在其他源文件内使用。同上(如果修饰的全局变量只在一个文件中使用,那么const的作用和前面所说的函数局部变量没有什么区别。文件之间共享,用extern
修饰类成员变量声明为static的类成员称为类的静态成员用static修饰的成员变量,称之为静态成员变量;静态成员变量必须在类外定义,定义时不添加static关键字,但需要添加作用域限定符声明.const修饰类成员变量与修饰局部或全局变量类似,其在使用时不能被修改,因此必须在对象实例化时初始化,(利用构造函数初始化列表)。
修饰类成员函数

用static修饰的成员函数,称之为静态成员函数。特性如下:

1.静态成员为所有类对象所共享,不属于某个具体的实例;
2.静态成员变量必须在类外定义,定义时不添加static关键字;
3.类静态成员即可用(类名::静态成员)或者(对象.静态成员)来访问。
4.静态成员函数没有隐藏的this指针,不能访问任何非静态成员
5.静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值
 

将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。但也可在某些变量前加上mutable关键字,其在对对象进行操作的过程中可以被修改。
修饰类对象static不能修饰一个普通类,但是可以修饰内部类;被修饰的内部类可以被当成一个普通类来使用,不需要先实例化出一个外部类。const修饰类对象,对象中的变量均不可被修改,其只能调用const成员函数。非const对象既可以调用普通成员函数也可以调用const成员函数。由于有时需要创建const对象,因此在定义类时往往要将const函数与普通成员函数一并给出。

参考:

1.浅谈堆、栈、堆区、栈区的概念和区别_蝶开三月的博客-CSDN博客_堆区

2.对堆区、栈区、全局静态区的理解_kwenZh的博客-CSDN博客_全局区和静态区

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值