当前位置: 首页> 娱乐> 八卦 > 下载赶集网招聘最新招聘_企业为什么要上市_网站建设制作流程_学生网页制作成品

下载赶集网招聘最新招聘_企业为什么要上市_网站建设制作流程_学生网页制作成品

时间:2025/7/29 14:19:07来源:https://blog.csdn.net/2301_80029060/article/details/145535035 浏览次数:0次
下载赶集网招聘最新招聘_企业为什么要上市_网站建设制作流程_学生网页制作成品

本文是C++内存管理部分的学习分享 希望能够对你有所帮助~

那咱们废话不多说,直接开始吧!


1. 内存分布

1.1 引入

在开始之前,我们先来看一道题目:

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);
}

选择题:  

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

globalVar在哪里?____    

staticGlobalVar在哪里?____  

staticVar在哪里?____    

localVar在哪里?____  

num1 在哪里?____

char2在哪里?____    

*char2在哪里?___  

pChar3在哪里?____        

*pChar3在哪里?____  

ptr1在哪里?____          

*ptr1在哪里?____

思考的差不多了吗?答案揭晓:

变量/表达式存储区域
globalVarC(数据段)
staticGlobalVarC(数据段)
staticVarC(数据段)
localVarA(栈)
num1A(栈)
char2A(栈)
*char2A(栈)
pchar3A(栈)
*pchar3D(代码段/常量区)
ptr1A(栈)
*ptr1B(堆)

其实理解起来并不困难:

全局变量以及静态局部变量都在数据段上;

在函数中除了静态成员变量外,其他的变量都存在这个函数的栈帧中;(因此我们经常说出了函数成员变量也随之消失,本质上还是因为函数的栈帧内存归还给系统了)

只能读、多个进程共享的(这部分会在后续的学习中分享)且大小不变的数据都放在代码段中;

动态开辟的空间就是开在堆上的


1.2 内存区域划分

C/C++ 程序的内存区域划分如下:

内存区域描述
存储非静态局部变量、函数参数、返回值等,向下增长。
动态内存分配区域,向上增长。
数据段(静态区)存储全局变量、静态变量(如 staticGlobalVar 和 staticVar)。
代码段(常量区)存储可执行代码和只读常量(如字符串常量 "abcd")。
内存映射段用于文件映射、动态库加载等,用户可通过系统接口创建共享内存。

 


2. C语言动态内存管理

2.1 函数区别

  • malloc:分配指定字节的未初始化内存。

  • calloc:分配并清零初始化内存(参数为元素个数和大小)。

  • realloc:调整已分配内存的大小(可能迁移数据)。

2.2 注意事项

  • realloc 后,原指针 p2 可能失效,需直接释放 p3(见示例代码)。

void Test ()
{// 1.malloc/calloc/realloc的区别是什么?int* p2 = (int*)calloc(4, sizeof (int));int* p3 = (int*)realloc(p2, sizeof(int)*10);// 这里需要free(p2)吗?free(p3 );
}

3. C++内存管理(new/delete)

3.1 基本用法

int* ptr4 = new int;          // 分配一个 int  
int* ptr5 = new int(10);      // 分配并初始化为 10  
int* ptr6 = new int[3];       // 分配 3 个 int 的数组  

delete ptr4;                  // 释放单个对象  
delete[ ] ptr6;                // 释放数组  

3.2 自定义类型

  • new:调用构造函数。

  • delete:调用析构函数。

class A { /* ... */ };  
A* p2 = new A(1);  // 调用构造函数  
delete p2;         // 调用析构函数  

3.3 注意事项

看完上述对于内置类型以及自定类型的基本用法后,也许思维活跃的你就会想到:那如果我创建了多个自定义类型变量,但我就只用delete还能够达成我释放内存的目的吗?

class A
{
public:A(int a=1,int b=1){_a = a;_b = b;}~A(){cout<<"~A()"<<endl;}
private:int _a;int _b;
};
int main()
{A* p7 = new A[10];delete p7;return 0;
}

事实上,在我们运行代码后会发现系统报错了,为什么呢?

这里涉及到一个内存泄漏的问题:

首先当然就是只能释放一个对象的问题

当然,不只是这个

按理来说一个A类的对象大小根据内存对齐规则来定应该为8,那么我们这里开了10个对象就应该是开了80字节的空间,但我们检查一下会发现一个很神奇的现象

内存大小成了84个字节?!发生甚么事了?

其实另外的四个字节是用来存储对象个数的,拿这段代码来说是A[10]的这个10,并且这个数字存储的位置非常特殊,在指向的空间的前面

但是在调用delete的时候是直接从p7只想的位置释放的,那前面的这四个字接就泄露了......

但是为什么要保存这个成员个数呢?别急,答案将在下面第五点的实现原理部分揭晓~


4. operator new 与 operator delete函数

  • operator new:底层通过 malloc 实现,失败时抛出异常(malloc 返回 NULL)。

  • operator delete:底层通过 free 实现。

代码示例

void* operator new(size_t size) {  void* p = malloc(size);  if (p == nullptr) throw bad_alloc();  return p;  
}  

5. new/delete 的实现原理

5.1 内置类型

  • 与 malloc/free 类似,但支持异常机制。

5.2 自定义类型

  • new

    1. 调用 operator new 分配内存。

    2. 调用构造函数。

  • delete

    1. 调用析构函数。

    2. 调用 operator delete 释放内存。

因此,刚刚说到的10实际上是给delete[ ]用的,是要告诉它有多少个成员,这样它就知道需要调用多少次析构函数了,真是太~妙~了~

我们这时将写的显式析构函数注释掉:

class A
{
public:A(int a=1,int b=1){_a = a;_b = b;}//~A()//{//cout<<"~A()"<<endl;//}
private:int _a;int _b;
};
int main()
{A* p7 = new A[10];delete p7;return 0;
}

再计算一次,发现新生成的内存大小会发现又变回80了

我也不卖关子了,这是因为类中没有了显式析构函数,构造函数中也没有额外申请资源(申请内存),那么系统就会认为此时的默认析构函数可调可不调,从而进行了优化,直接在p7开始指向的位置直接进行内存释放。

但不管怎么说,咱老老实实地将new与delete正确匹配着来用准没错!


6. malloc/free 与 new/delete 的区别

区别点malloc/freenew/delete
类型函数操作符
初始化不初始化new 可初始化
大小计算需手动计算自动计算(类型 + 数量)
返回值void*(需强转)类型指针(无需强转)
失败处理返回 NULL抛出异常
构造/析构不调用调用构造/析构函数


那么以上便是本次内存管理部分学习分享的全部内容了

十分感谢你能够看到这里~

如果感觉对你有帮助的话也请给我一键三连 这将会给我莫大的鼓舞!

后续我依旧会持续更新其他的内容 敬请期待

那么 就让我们

下次再见~

关键字:下载赶集网招聘最新招聘_企业为什么要上市_网站建设制作流程_学生网页制作成品

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: