【C++系列P6】C/C++的内存管理(超细超有料!YY打包票!)

简介: 【C++系列P6】C/C++的内存管理(超细超有料!YY打包票!)

前言

  • 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎!
  • 本章主要内容面向接触过C++的老铁,主要内容含

一.C/C++的内存管理

1.C/C++的内存分布规则

栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。

内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)

堆用于程序运行时动态内存分配,堆是可以上增长的。

数据段--存储全局数据和静态数据。

代码段--可执行的代码/只读常量。

图示:  

一.易错点:数组存储字符串和指针指向字符串,解引用后所在的位置不同(含例题)

*char2数组所在的位置是栈,是位于代码段(常量区)"abcd\0"的一份拷贝;

pChar3是一个指向代码段(常量区)"abcd\0"的一个指针变量,由于其具有常性,所以要加上const;

图示:

2.C/C++的内存管理方式

PS:C的内存管理有malloc/calloc/realloc/free(可见博主C专栏:动态内存管理)  


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


一.使用new和delete操作符的使用规范

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[],要匹配起来使用。(如果new后接free,无论是否是对同一块空间的操作,都容易报错)


代码演示:

//报错
int* p3 = (int*)malloc(sizeof(int)); // C
int* p4 = new int;
free(p4);           对开辟同一块空间操作,不匹配
delete p3;
//报错
int* p3 = (int*)malloc(sizeof(int)); // C
int* p4 = new int;
free(p3);           对开辟不同一块空间操作,不匹配
delete p4;

二.new和delete对内置类型的具体使用场景

使用场景:

  • 申请一个int类型空间(调用构造,随机值)
  • 申请一个int类型空间,并初始化为10
  • 申请10个int类型空间
  • 申请10个int类型空间,并分别初始化

代码演示:

void Test()
{
  // 动态申请一个int类型的空间
  int* ptr4 = new int;
  // 动态申请一个int类型的空间并初始化为10
  int* ptr5 = new int(10);
  // 动态申请10个int类型的空间
  int* ptr6 = new int[10];
  // 动态申请10个int类型的空间,并初始化
  int* ptr7 = new int[10]{1,3,4};
  delete ptr4;
  delete ptr5;
  delete[] ptr6;
}

三.new和delete对自定义类型的具体使用场景

使用场景:有一个自定义类型A,他的初始化列表需要传入两个参数

  • 申请一个空间给A
  • 申请一个4个空间给4个A,分别初始化(多参,不可不完全初始化)

代码演示:

void test()
{
  A* p1 = new A(1,1);
  delete p2;
  //错误写法:不完全初始化  A* p2 = new A[4]{ A(1,1),A(2,2),A(3,3)};
  A* p2 = new A[4]{ A(1,1),A(2,2),A(3,3),A(4,4) };
  delete[] p2;
}

四.new/delete与malloc/free的底层区别(自定义类型演示)

new/delete 和 malloc/free根本区别:


new的底层其实也是malloc,与malloc不同之处在于他会调用拷贝构造

delete的底层其实也是free,与free不同之处在于他会调用析构函数

实例分析:(顺序)


在下图中,new了一个栈Stack,其实底层是先malloc个空间给Stack(自定义类型),再调用它的拷贝构造(_array指向的新空间);

当delete栈Stack时,先调用析构函数(free掉刚刚_array指向的新空间),再free掉Stack所处的空间;

PS:如果不是这样,而是先free掉Stack的空间,那么_array指向的新空间将无法被p1找到,造成内存泄漏

图演示:  

五. new/delete与malloc/free在使用失败时的区别

  • C++是一门面向对象的语言,处理失败时,不喜欢用返回值,更喜欢用抛异常
  • 一般用【try-catch捕捉

代码演示:

    try
  {
  do
  {
    //p1 = (int*)malloc(1024 * 1024);
    p1 = new int[1024 * 1024];
    cout << p1 << endl;
  } while (p1);
  }
catch (const exception& e)
{
  cout << e.what() << endl;
}
相关文章
|
1月前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
10 4
|
1月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
91 21
|
20天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
24天前
|
存储 C语言 C++
【C++打怪之路Lv6】-- 内存管理
【C++打怪之路Lv6】-- 内存管理
34 0
【C++打怪之路Lv6】-- 内存管理
|
1月前
|
存储 C语言 C++
【C/C++内存管理】——我与C++的不解之缘(六)
【C/C++内存管理】——我与C++的不解之缘(六)
|
1月前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
59 1
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
134 1
|
1月前
|
存储 安全 程序员
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
59 3