【C++】深入解析C/C++内存管理:new与delete的使用及原理(一)

简介: 【C++】深入解析C/C++内存管理:new与delete的使用及原理

一、C/C++中程序内存区域划分

内存区域相关作用:

  • 栈又叫堆栈:非静态局部变量、函数参数、返回值等等,栈是向下增长的
  • 内存映射段时高效的I/O映射方式,用于装载一个共享的动态内存库,用户可以使用系统接口创建共享共享内存,做进程间通信
  • 堆用于程序运行时动态内存分配,堆时可以上增长的
  • 数据段:存储全局数据和静态数据
  • 代码段:可执行的代码、只读常量

在语法上将数据段称为静态区、代码段称为常量区,而以上操作系统的命名。

提出相关思考:

  1. 为什么要分不同的区域
  2. 哪个区域是我们需要重点关注的

回答:

  1. 根据对象不同的生命周期和作用域,分配到不同的区域中,统一管理,高效地对对象进行处理
  2. 堆是我们要需要重点关注的,这是系统留给我们控制的内存,其他系统是自动的

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

答案:

  • 选择题:C、C、C、A、A 。A、A、A、D、A、B
  • 填空题:40、5、4、4/8、4、4/8

这里容易混洗的char str1[] ="abcd"const char* str2 ="abcd"。这里str1是个数组将常量拷贝到数组,而str2是直接指向常量区中常量。

二、C语言中动态内存管理方式

C语言中,系统通过一系列函数赋予了我们对堆上空间的控制

void Test ()
{
int* p1 = (int*) malloc(sizeof(int));
free(p1);
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
free(p3 );
}

提出思考:

  1. malloc/calloc/realloc的区别是什么?
  2. 这里使用realloc是否还需要free(p2)
  3. malloc的实现原理?

第一个问题的回答:

对于malloc/calloc/realloc是系统为我们提供在堆上申请空间的途径。在功能上大体是相同的,对于malloccalloc这两个函数,除了参数部分及其是否完成初始化,其他功能是相同的。

relloc比较特别,属于扩容时使用的函数。扩容有两种方式:原地扩容和异地扩容。如果realloc第一个参数部分为空,可以当作malloc使用)。具体还是参考下这篇博客有详细解释内存管理

第二个问题的回答:

由于realloc进行了扩容操作。如果是原地扩容,在原来开辟空间上完成扩容操作,这里p3会同p2指向这块空间,只需要free(p3);如果是异地扩容,将p2空间中数据拷贝一份,在堆上找一块空间充足地方,完成扩容和拷贝操作,p2指向原空间,会被系统自动收回,不需要对p2进行free操作。对此无论是原地还是异地,只需要free(p3)即可

第三个问题的回答:

可以通过该链接进行学习GLibc堆利用入门

三、C++内存管理方式

在C++中,虽然可以继续使用C语言对于内存管理方式,但是在有些地方就无能为力,而且使用起来比较麻烦。对此因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理

3.1 使用new/delete进行数据操作

3.1.1 new/delete 操作内置类型

int main()
{
  //动态申请一个int类型的空间
  int* ptr1 = new int;
  //动态申请一个int类型的空间并且初始化为10
  int* ptr2 = new int(10);
  //动态申请10个int类型的空间
  int* ptr3 = new int[3];
  //动态申请10个int类型的空间并且完成初始化
  int* ptr4 = new int[10]{ 1,2,3 };//剩下没有明确给值,默认为0
  delete ptr1;
  delete ptr2;
  delete []ptr3;
  delete[]ptr4;
  return 0;
}

注意需要匹配使用new和delete操作符:

  • 申请和释放单个元素的空间:new、delete
  • 申请和释放多个元素的空间:new[]、delete[]

3.1.2 new和delete操作自定义类型

class A
{
public:
  A(int a = 0)
    :_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);
  A* p6 = new A[10];
  free(p5);
  delete[] p6;
  return 0;
}

从结果上来看,对于newmalloc最大差别在于对自定义类型除了开辟空间以外,还会调用构造函数和析构函数及其进行良好的初始化和控制。对于malloc而言无法对自定义类型进行好的初始化和控制,只负责开辟内存,除此之外内置类型几乎相同(初始化不同)

对于new优于malloc的几点:

  1. 用法上进行调正,更简洁好用
  2. 可以控制初始化
  3. 对于自定义类型,new可以开空间+构造函数
  4. new配合构造函数,可以更加便捷创建节点等
  5. new失败了以后抛异常,不需要手动检查


【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)https://developer.aliyun.com/article/1617322

相关文章
|
1天前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1天前
|
存储 安全 程序员
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
17 3
|
1天前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
2月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
178 0
|
3月前
|
存储 分布式计算 Hadoop
HadoopCPU、内存、存储限制
【7月更文挑战第13天】
222 14
|
2月前
|
存储 监控 Docker
如何限制docker使用的cpu,内存,存储
如何限制docker使用的cpu,内存,存储
|
3月前
|
存储 固态存储 芯片
计算机中内存与存储
【7月更文挑战第28天】
46 1
|
3月前
|
存储 弹性计算 程序员
新手程序员如何阿里云服务器配置?新人开发者CPU内存带宽存储怎么选?
对于新手开发者、个人或学生选择阿里云服务器,推荐ECS经济型e实例(ecs.e-c1m1.large),适用于小型网站或轻量应用。配置2核2G内存、3M固定带宽、40G ESSD系统盘,仅99元/年且续费同价。
|
2月前
|
存储 编译器 C语言
数据在内存中的存储
数据在内存中的存储
|
3月前
|
存储 Java 程序员
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
57 10

热门文章

最新文章

推荐镜像

更多