C++的内存分布及内存管理

简介: C++的内存分布及内存管理

对于C语言和C++而言,它们的内存分布都是一样的

而内存是编写程序时必须要关心的点,一定要防止内存过载 内存泄漏等问题

一旦内存出现问题程序就会直接崩溃,甚至严重的还会导致系统死机等

C/C++的内存分布

C/C++的内存分布可以简易的划分为以下图示


7eabe771d5ed8f66cc26b6ec099a9c4c.png

不同的数据会存放在对应的空间中

  1. 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的
  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库
  3. 堆存放动态开辟的内存分配,堆是可以上增长的。
  4. 数据段–存储全局数据和静态数据
  5. 代码段–可执行的代码/只读常量

C++的动态内存管理

对于C语言想要开辟一块内存可以用到 malloc、calloc、realloc这三个函数,而对于C++也有自己的开辟内存方式-- new负责开辟空间 delete负责释放空间。前者是C语言中的函数,而后者是C++中的操作符

new、delete的使用

int main() {
  //开辟一块int类型的空间并初始化为10
  int* a = new int(10);
  //开辟一块char类型的空间
  int* b = new int;
  //开辟一块连续的有10个double类型的空间
  double* c = new double[10];
  //如果申请的空间只有一个时
  delete a;
  a = nullptr;
  delete b;
  b = nullptr;
  //申请了连续空间时
  delete[] c;
  c = nullptr;
  return 0;
}

new/delete和malloc/free使用上的区别

  1. malloc申请出来的空间不可以进行初始化,但new可以
  2. malloc的返回值为void* 因此需要强转为指定类型,而new不需要
  3. malloc开辟空间时需要计算出空间的字节大小,而new不用它会自动识别类型只需要在[]里输入个数即可
  4. malloc开辟失败会返回NULL,new会捕捉异常
  5. 申请自定义类型空间时,malloc/free不会调用构造和析构函数,new会调用构造函数并且在delete释放空间前会调用析构函数清理资源

new和delete的底层原理

其实这两个的底层也是用malloc和free实现的,在C++中有两个全局函数 operator new、operator delete。这两个全局函数使用malloc和free定义的。在用户调用new和delete,它们会分别调用这两个全局函数。

new调用operator new函数申请空间,并执行对应类型的构造函数完成对象的初始化

delete首先会执行对应类型的析构函数,然后再调用operator delete释放空间

new T[N] 这种连续的开辟空间实际上会调用N次构造函数

delete[] 也就是会调用N次析构函数,不需要指明N

了解内存泄漏

内存泄漏是一种经常会出现的情况,如果是长期运行的程序出现了内存泄漏就会慢慢的导致系统卡死。

内存泄露可能出现的情况:

  1. 堆内存泄露也就是当用户开辟了空间后没有释放掉,那这部分空间就会一直无法被操作系统收回也就无法再次使用,长期积累就会导致内存空间不足
  2. 野指针的问题也会导致空间找不回来系统收不回去

因此在写程序时一定要额外的注意内存问题,只要有开辟了空间就一定要记得使用完之后释放。

目录
相关文章
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
12月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
408 26
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
218 1
|
存储 缓存 编译器
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
814 68
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
692 0
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
779 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
560 12
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)