c++b

Last edited time
Sep 17, 2024 10:58 AM
AI summary
C++内存管理包括静态全局变量、全局变量、静态局部变量和局部变量的区别,以及内存的五个区域:堆区、栈区、自由存储区、全局/静态存储区和常量存储区。堆和栈在分配效率、碎片问题、生长方向和分配方式上有显著不同,堆支持动态分配但可能导致内存碎片,而栈则由编译器自动管理内存。
Last edited by
Tags
1、静态全局变量、全局变量、静态局部变量、局部变量的区别
  • 静态全局变量、全局变量的区别
    • 静态全局变量和全局变量都存储在全局/静态存储区
      静态全局区只在本⽂件有效,不可extern到其他⽂件,⽽全局变量可以extern到别的⽂件中调⽤。
      如果别的⽂件中定义了⼀个和该全局变量相同的变量名,会报错。
  • 静态局部变量(⽐如函数内部的变量⽤ static 修饰)、局部变量的区别
    • 静态局部变量是属于常量区的,⽽函数内部的局部变量属于栈区;
      静态局部变量在该函数调⽤结束时,不会销毁,⽽是随整个程序结束⽽结束,但是别的函数调⽤不了该变量,局部变量随该函数的结束⽽结束;
      如果定义这两个变量的时候没有初始值时,静态局部变量会⾃动定义为0,⽽局部变量就是⼀个随机值;
      静态局部变量在编译期间只赋值⼀次,以后每次函数调⽤时,不在赋值,调⽤上次的函数调⽤结束时的值。局部变量在调⽤期 间,每调⽤⼀次,赋⼀次值。
  1. 在c++中,内存分为 5 个区,
      • 堆区heap:分配堆区内存也叫动态内存分配。程序在运⾏的时候使⽤  malloc  申请任意多少的内存,程序员⾃⼰负责在何时⽤  free  释放内存。动态内存的⽣命周期由程序员决定,使⽤⾮常灵活,但如果在堆上分配了空间,既有责任回收它,否则运⾏的程序会出现内存泄漏,频繁的分配和释放不同⼤⼩的堆空间将会产⽣内存碎⽚,如果程序员没有释放掉,那么在程序结束后,操作系统会⾃动回收。
      • 栈区:在执⾏函数时,函数内局部变量的存储单元可以在栈上创建,函数执⾏结束时,这些内存单元会⾃动被释放。栈内存分配运算内       置于处理器的指令集,效率⾼,但是分配的内存容量有限。⾥⾯的变量通常是局部变量、函数参数、返回数据、返回地址等。由编译器⾃动分配释放。
      • ⾃由存储区:就是那些由 new/delete 等分配的内存块,他和堆是⼗分相似的,也是⽤户来申请释放内存。
      • 全局/静态存储区:内存在程序编译的时候已经分配好,这块内存在程序的整个运⾏期间都存在。例如全局变量,static静态全局变量。程序结束后由系统释放。
      • 常量存储区:存放常量、字符串、静态局部变量,程序结束后有系统释放。
        • 在所有函数体外定义的是全局量,加了static修饰符后不管在哪⾥都存放在全局区(静态区),⽽且表⽰在该⽂件中有效,不能extern到别的⽂件⽤。在函数体内定义的static(静态局部变量)表⽰只在该函数体内有效。另外,函数中像 “adgfdf” 这样的字符串存放在常量存储区
  1. 堆与栈的关系和区别
      • 分配效率上。现代计算机有专门的寄存器指向栈所在的地址,有专门的机器指令(push,pop)完成数据入栈出栈的操作,这种机制 的特点是效率⾼,⽀持的数据有限,⼀般是整数,指针,浮点数等系统直接⽀持的数据类型,并不直接⽀持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的。而堆的数据结构并不是由系统(无论是机器系统还是操作系统)⽀持的,而是由函数库提供的。基本的malloc/realloc/free 函数维护了⼀套内部的堆数据结构。从以上知识可知,栈是系统提供的功能,特点是快速⾼效,缺点是有限制,数据不灵活;⽽堆是函数库提供的功能,特点是灵活⽅便,数据适应面广泛,但是效率有⼀定降低。栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可移植的程序起见,栈的动态分配操作是不被⿎励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹配是良好程序的基本要素。
      • 碎片问题:对于堆来讲,频繁的new/delete 或者 malloc/free 势必会造成内存空间的不连续,从⽽造成⼤量的碎⽚,使程序效率降低。 对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,以⾄于永远都不可能有⼀个内存块从栈中间弹出,在他弹出之前,在他上⾯ 的后进的栈内容已经被弹出。
      • 生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的⽅向增长。
      • 分配方式:堆都是动态分配的,没有静态分配的堆。栈有 2 种分配⽅式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进⾏分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
Loading...