C/C++内存管理

简介: C/C++内存管理

C/C++内存管理

C++兼容C语言C++的内存管理机制和C语言是一样的,但是C语言malloc函数已经无法满足C++面对对象过程中销毁的需求,于是C++提出了新的内存管理函数newdelete

1. C/C++内存分布

将内存分成不同的区域是为了更好的管理,上面说过C++兼容C,所以内存分布都是一样的:

171c05f057cb2ef524b5321998c64dde.png五大分区:

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

内存中还存在内核空间,但普通用户代码无法读写

2. C++动态内存管理

内存管理是为了对内存进行分类,使操作系统对内存能有更让的管理,C++提出了newdelete操作符进行动态内存管理,下面我们来讲讲使用细节

2.1 new和delete操作内置类型

代码演示:

void Test()
{
  int* ptr1 = new int; //申请一个整型,只是开空间
  delete ptr1; //释放
  double* ptr2 = new double(6.66); //申请一个浮点型,并初始化为6.66
  delete ptr2; //释放
  int* ptr3 = new int[8]; //申请8个int类型的空间
  delete[] ptr3; //释放8次
}

2.2 new和delete操作自定义类型

代码演示:

class A
{
  A(int a = 12)
    :_a(a)
  {
    cout << "A()" << endl;
  }
  ~A()
  {
    cout << "~A()" << endl;
  }
private:
  int _a;
};
int main()
{
  //new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
  A* p1 = (A*)malloc(sizeof(A)); //开空间
  A* p2 = new A(12); //开空间并初始化
  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); //开10个A类对象空间
  A* p6 = new A[10]; //开10个A类对象空间
  free(p5);
  delete[] p6;
  return 0;
}

总结:

  1. new不需要像malloc那样进行空指针判断,也不需要进行类型转换
  2. delete需要配套使用,比如new int 使用 deletenew int 使用 delete[]
  3. newdelete都可以用于自定义类型,会分别调用自定义类型的构造函数析构函数
  4. new/deletemalloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数析构函数
  5. malloc 对应freenew 对应 delete,一定要搭配使用,避免引发问题

3. operator new 和 operator delete函数

newdelete是用户进行动态内存申请和释放的操作符,operator newoperator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

Visual studio 2019中operator new底层实现:

void* __CRTDECL operator new(size_t const size)
{
  for (;;)
  {
    if (void* const block = malloc(size))
    {
      return block;
    }
    if (_callnewh(size) == 0)
    {
      if (size == SIZE_MAX)
      {
        __scrt_throw_std_bad_array_new_length();
      }
      else
      {
        __scrt_throw_std_bad_alloc(); //抛出异常
      }
    }
    // The new handler was successful; try to allocate again...
  }
}

Visual studio 2019中operator delete底层实现:

void __CRTDECL operator delete(void* const block, size_t const) noexcept
{
  operator delete(block);
}
void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
  _free_dbg(block, _UNKNOWN_BLOCK);
#else
  free(block);
#endif
}

Visual studio 2019中operator new[]底层实现:

void* __CRTDECL operator new[](size_t const size)
{
  return operator new(size); //原理调用的size次operator new函数
}

Visual studio 2019中operator delete底层实现:

void __CRTDECL operator delete[](void* const block) noexcept
{
  operator delete(block);
}
void __CRTDECL operator delete[](void* const block, size_t const) noexcept
{
  operator delete[](block);
}

4. new 和 delete实现原理

4.1 内置类型

如果申请的是内置类型的空间,newmallocdeletefree基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL

4.2 自定义类型

new的原理:

  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数,完成对象的构造

delete的原理:

  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间

new T[N]的原理:

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对

象空间的申请

  1. 在申请空间上执行N次构造函数

delete[]的原理:

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

5. 定位new

定位newnew的新用法,是为了对已经开辟但没有初始化的空间进行初始化

5.1 基本语法

定位new表达式是:在已分配的原始内存空间中调用构造函数初始化一个对象

使用格式:new(指针)type或者new(指针)type(初始化列表)

代码使用:

class A
{
public:
  A(int a)
    :_a(a)
  {
    cout << "A()" << endl;
  }
  ~A() {
    cout << "~A()" << endl;
  }
private:
  int _a;
};
int main()
{
  A* p = (A*)malloc(sizeof(A));
  if (p == nullptr) {
    perror("malloc is failed");
    exit(-1);
  }
  new(p)A(1); //定位new,对已经定义的对象初始化
  return 0;
}

5.2 使用场景

使用场景:一般配合内存池使。因为内存池分配出的内存没有初始化,所以如果定义自定义类型对象,需要使用new的定义表达式进行显示调用构造函数进行初始化

C/C++内存管理到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!

文章有写的不足或是错误的地方,欢迎评论或私信指出,我会在第一时间改正

目录
相关文章
|
15天前
|
存储 编译器 C语言
内存管理【C++】
内存管理【C++】
33 1
|
29天前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
27天前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
8天前
|
C语言 C++
C++(二)内存管理
本文档详细介绍了C++中的内存管理机制,特别是`new`和`delete`关键字的使用方法。首先通过示例代码展示了如何使用`new`和`delete`进行单个变量和数组的内存分配与释放。接着讨论了内存申请失败时的处理方式,包括直接抛出异常、使用`try/catch`捕获异常、设置`set_new_handler`函数以及不抛出异常的处理方式。通过这些方法,可以有效避免内存泄漏和多重释放的问题。
|
30天前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
1月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
58 5
|
22天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
35 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++特性能进一步帮助管理内存。
|
2月前
|
存储 编译器 程序员
【C/C++】动态内存管理(C:malloc,realloc,calloc,free)
探索C++与C语言的动态内存管理:从malloc到new/delete,了解内存分布及栈、堆的区别。文章涵盖malloc、realloc、calloc与free在C中的使用,强调内存泄漏的风险。C++引入new和delete,支持对象构造与析构,还包括operator new和placement-new。深入分析内存管理机制,揭示C与C++在内存处理上的异同。别忘了,正确释放内存至关重要!