内存管理(C++版)

C/C++内存分布

程序经过编译生成可执行的二进制程序,我们可以把虚拟进程地址分为以下四个空间:栈,堆,常量区,静态区。这四个区里面存贮的也是不一样的内容。

各个区域所存储内容的说明

  • 栈/堆栈:用于建立函数栈帧,主要存储一些临时变量,如(非静态局部变量/函数参数/返回值等等),栈空间很小,在Linux中大概是8M。栈是向下增长的。
  • 内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做进程间通信。
  • 堆:用于程序运行时动态内存分配,堆是可以上增长的。栈空间很大,在Linux中大概是以G为单位。
  • 静态区/数据段:存储全局数据和静态数据。
  • 常量区/代码段:可执行的代码/只读常量。

下面通过面试体案例进行讲解各部分所在的位置

int globalVar = 1;

static int staticGlobalVar = 1;

void Test()

{

static int staticVar = 1;

int localVar = 1;

int num1[10] = { 1, 2, 3, 4 };

char char2[] = "abcd";

const char* pChar3 = "abcd";

int* ptr1 = (int*)malloc(sizeof(int) * 4);

int* ptr2 = (int*)calloc(4, sizeof(int));

int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);

free(ptr1);

free(ptr3);

}

  1. 选择题: 选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)

globalVar在哪里?C

staticGlobalVar在哪里?C__

staticVar在哪里?C__

localVar在哪里?A__

num1 在哪里?__A

char2在哪里?A__

*char2在哪里?_A

pChar3在哪里?A

*pChar3在哪里?D

ptr1在哪里?A

*ptr1在哪里?B

解析:

nums1是一个数组,存放在栈区,char2也是一个数组 ,它是在常量区有一串字符串,字符串拷贝到char2数组中,pChar3是一个指针,指针存的是常量字符串首元素的地址,这里*pChar3就是在常量里面了,ptr1开辟的是指向堆区的空间,因此*ptr指向的是堆区。

动态管理方式

C语言中malloc/calloc/realloc/frees用法

malloc:void * malloc (size_t size);

  • 申请一块大小为 size 的内存空间,申请成功,返回指向这块空间起始位置的指针
  • 新分配的内存块没有初始化,保留不确定的值
  • 如果函数无法分配申请的内存块,会返回一个空指针 (NULL),因此 malloc 函数的返回值一定要检查
  • 此函数只负责申请 size 大小的内存空间,并不知道未来会存放什么类型的数据,因此函数的返回值是 void*

calloc:void* calloc (size_t num, size_t size);

  • 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为 0

realloc:void* realloc (void* ptr, size_t size);

  • 函数的出现让动态内存管理更加灵活,能够合理的使用内存,对内存的大小做灵活的调整。realloc 函数就可以做到对动态开辟内存大小的调整

C++中使用的有new后面只有跟着申请的类型,在初始化的时候new 类型后面要加上(初始化的值),在申请多个的情况就是new 类型后面要加上 [],申请多个并进行初始化的时候在[]后面加上{}初始化{}不赋值就是默认值,因此构造函数一点要有一个默认值以便使用。delete删除时用delete+删除的变量名就行,删除多个时候就是delete 变量名+[]。

void Test()

{

// 动态申请一个int类型的空间

int* ptr4 = new int;

// 动态申请一个int类型的空间并初始化为10

int* ptr5 = new int(10);

// 动态申请3个int类型的空间

int* ptr6 = new int[3];

// 动态申请3个int类型的空间 并进行初始化

int* ptr6 = new int[3]{1,2,3};

delete ptr4;

delete ptr5;

delete[] ptr6;

}

C++中new delete相对与malloc free的优点

C++中的new不仅具可以开辟空间,还会进行函数的构造,delete相对与free不仅可以释放空间还会调用析构函数。

C++中new delete的用法

cpp 复制代码
class A
{
public:
 A(int a = 1)
 : _a(a)
 {
 cout << "A():" << this << endl;
 }
 ~A()
 {
 cout << "~A():" << this << endl;
 }
private:。
 int _a;
};
int main()
{
 
 A* p1 = (A*)malloc(sizeof(A));
 A* p2 = new A(1);
 free(p1);
 delete p2;

 int* p3 = (int*)malloc(sizeof(int)); 
 int* p4 = new int;

 free(p3);
 delete p4;

 A* p5 = (A*)malloc(sizeof(A)*10);
//前三个初始化1,2,3后面的就是默认值
 A* p6 = new A[10]{1,2,3};

 free(p5);
 delete[] p6;

 return 0;
}

new与delete的底层原理

operator new与operator delete是库函数,不是函数的重载。operator new是对malloc的封装而operator delete是对free_dbg函数的封装(这里可以理解为是对free函数的封装)。new和delete关键字是对operator new与operator delete的调用。

下图是通过反汇编来更好的理解new的底层:

new A[N]的原理

  • 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
  • 在申请的空间上执行N次构造函数

delete[N]的原理

  • 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  • 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释 放空间
相关推荐
zh路西法4 分钟前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
c++·决策树·状态模式
大G哥6 分钟前
java提高正则处理效率
java·开发语言
stm 学习ing6 分钟前
HDLBits训练5
c语言·fpga开发·fpga·eda·hdlbits·pld·hdl语言
VBA633716 分钟前
VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL
开发语言
轩辰~18 分钟前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
小_太_阳27 分钟前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
向宇it28 分钟前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
lxyzcm38 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿1 小时前
C/C++基础错题归纳
c++
古希腊掌管学习的神1 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode