【C++初阶】C++内存管理(上)

简介: 【C++初阶】C++内存管理

一.C/C++内存分布图

作为C/C++方向的从业者,必须关注的四块空间:

  1. 栈(局部数据)
  2. 堆(动态申请数据)
  3. 数据段(全局数据和静态数据)
  4. 代码段(可执行代码和可读常量)

c183bbac2152220438970e5685e90bab.png

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

a829d7858e89cc9dcce914643b57e82e.png

解析:


globalVar定义在所有的函数外,所以是全局变量,位于数据区


staticGlobalVar定义在函数体外[全局],且被static修饰[静态],所以是静态(全局)变量,位于数据区


staticVar定义在函数体外[局部],且被static修饰[静态],所以是静态(局部)变量,位于数据区


localVar定义在函数体内[局部],所以是局部变量,位于栈区


num1是整型数组名,定义在函数体内[局部],所以是局部变量,位于栈区


char2是字符数组名,定义在函数体内[局部],所以是局部变量,位于栈区


*char2是字符数组存放的内容,位于栈区


pChar3是一个指针,指向代码段中常量字符串“abcd”,定义在函数体内[局部],位于栈区


*pChar3是常量字符串“abcd”,位于代码段


ptr1指向动态申请的空间,定义在函数体内[局部],位于栈区


*ptr1是动态申请的空间里的内容,位于堆区


关于第7题和第9题区别:

b169b0cc6704dab52de183b4cb50da04.png

二.new和delete内存管理

C 语言中的malloc是函数,C++中的new是关键字,操作符,都是在堆上动态申请的空间

下面我针对内置类型和自定义类型比较new,delete和malloc,free


1.对于内置类型

C 语言和C++默认都没有对各自动态申请的内存进行初始化

97cbc592808026f88884072c028727f4.png

int main()
{
  //C语言
  int* p1 = (int*)malloc(40);
  free(p1);
  //C++,默认不初始化
  int* ptr1 = new int;
  delete ptr1;
  //指定初始化
  int* ptr2 = new int(100);
  //ptr2 = nullptr;如果后面不使用了,可以置空
  delete ptr2;
  //动态申请数组
  //不初始化
  int* ptr3 = new int[10];
  delete[] ptr3;
  //完全初始化
  int* ptr4 = new int[10]{ 1,2,3,4,5,6,7,8,9,10 };
  delete[] ptr4;
  //不完全初始化
  int* ptr5 = new int[10]{ 1,2,3,4,5 };
  delete[] ptr5;
  return 0;
}

3a2fafa925f2b0d0743f1e29884d17c0.png

对于内置类型:

new/delete相比与malloc/free,只是用法上的区别

2.对于自定义类型(重点)

new/delete主要是针对自定义类型设计的,对于自定义类型,

new除了在堆上开辟空间,还会自动调用构造函数,完成对象的初始化

delete除了在堆上释放空间,还会自动调用析构函数,完成对象的资源清理

class A
{
public:
  A(int a = 10)
    :_a(a)
  {
    cout << "构造函数" << endl;
  }
  ~A()
  {
    cout << "析构函数" << endl;
  }
private:
  int _a;
};
int main()
{
  A* ptr1 = new A;
  delete ptr1;
  cout << "____________________________________" << endl << endl;
  A* ptr2 = new A[4];
  delete[] ptr2;
  return 0;
}

2125e6025e1361ca5d9e16d95cae5e8a.png

案例:对于我们之前学过的单链表那块

C语言:

ListNode* BuyListNode(int val)
{
  ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
  newnode->_val = val;
  newnode->_next = nullptr;
}
int main()
{
    ListNode* n1 = BuyListNode(1);
  ListNode* n2 = BuyListNode(2);
  ListNode* n3 = BuyListNode(3);
  n1->_next = n2;
  n2->_next = n3;
    return 0;
}

C++:

struct ListNode
{
  int _val;
  ListNode* _next;
  ListNode(int val = 0)
    :_val(val)
    ,_next(nullptr)
  {}
};
int main()
{
  //创建链表
  ListNode* n1 = new ListNode(1);
  ListNode* n2 = new ListNode(2);
  ListNode* n3 = new ListNode(3);
  ListNode* n4 = new ListNode(4);
  ListNode* n5 = new ListNode(5);
  n1->_next = n2;
  n2->_next = n3;
  n3->_next = n4;
  n4->_next = n5;
  return 0;
}

d3c2af59895da30bd71cfd0ad2c376cd.png


目录
相关文章
|
3天前
|
程序员 编译器 C++
【C++核心】C++内存分区模型分析
这篇文章详细解释了C++程序执行时内存的四个区域:代码区、全局区、栈区和堆区,以及如何在这些区域中分配和释放内存。
14 2
|
1月前
|
存储 编译器 C语言
内存管理【C++】
内存管理【C++】
42 1
|
1月前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
1月前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
1月前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
24天前
|
C语言 C++
C++(二)内存管理
本文档详细介绍了C++中的内存管理机制,特别是`new`和`delete`关键字的使用方法。首先通过示例代码展示了如何使用`new`和`delete`进行单个变量和数组的内存分配与释放。接着讨论了内存申请失败时的处理方式,包括直接抛出异常、使用`try/catch`捕获异常、设置`set_new_handler`函数以及不抛出异常的处理方式。通过这些方法,可以有效避免内存泄漏和多重释放的问题。
|
1月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
67 5
|
1月前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
40 0
|
2月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
2月前
|
存储 C语言 C++
【C/C++】动态内存管理( C++:new,delete)
C++的`new`和`delete`用于动态内存管理,分配和释放内存。`new`分配内存并调用构造函数,`delete`释放内存并调用析构函数。`new[]`和`delete[]`分别用于数组分配和释放。不正确匹配可能导致内存泄漏。内置类型分配时不初始化,自定义类型则调用构造/析构。`operator new`和`operator delete`是系统底层的内存管理函数,封装了`malloc`和`free`。定位`new`允许在已分配内存上构造对象,常用于内存池。智能指针等现代C++特性能进一步帮助管理内存。