当前位置: 首页 > news >正文

C++内存管理详解

目录

1.C/C++中的内存

2.C++内存管理

2.1C语言内存管理

2.2new和delete

2.2.1概念及定义

 2.2.2自定义类型内存管理

2.2.3 delete与delete[ ]


1.C/C++中的内存

在C/C++中编译器会对不同的代码进行内存分配,给代码的内存区主要分为栈区、堆区、数据段(静态区)、代码段(常量区)。像常见的局部变量就分配在栈区,具体内存分区如图所示:

说明:

(1)又叫堆栈,主要储存非静态局部变量、函数参数、返回值等,且向下增长

(2)主要用于程序运行时动态分配内存,是向上增长的

(3)数据段主要储存全局数据(变量),静态数据(变量)

(4)代码段主要储存可执行代码、只读数据(数据)。

对于栈和堆的向下、向上调整:C/C++中的内存分区从代码段到栈是从低地址到高地址,向下增长的意思是使用栈时优先使用高地址内存,由高到低;向上增长的意思是有限使用低内存地址,由低到高。以代码为例:

#include<iostream>using namespace std;int main()
{int x = 0;int y = 0;int* a = (int*)malloc(sizeof(int));int* b = (int*)malloc(sizeof(int));cout << "x:" << &x << endl;cout << "y:" << &y << endl;cout << endl;cout << "a:" << a << endl;cout << "b:" << b << endl;return 0;
}

运行结果如下(VS2022 x86 Debug环境): 

可以看到在栈开辟的局部变量x,y:x比y先定义,x的地址也比y的地址大;对于在堆区开辟的a,b:a比b先开辟,a地址也比b小。但堆区不一定全是向上增长,为提高堆的利用效率,当开辟空间较小时可能会在之前的未使用的空间进行开辟。

2.C++内存管理

2.1C语言内存管理

C语言中利用malloc/calloc/realloc动态管理内存:

(1)malloc快速分配指定大小的内存,不进行初始化

void* malloc (size_t size);

(2)calloc既分配内存又进行初始化

void* calloc (size_t num, size_t size);

(3)realloc对指定位置内存进行再分配

void* realloc (void* ptr, size_t size);

2.2new和delete

2.2.1概念及定义

new和delete是C++中用于动态管理内存的运算符,new用于给对象开辟空间,delete用于销毁对象空间,具体语法定义如下(以内置类型为例):

#include<iostream>using namespace std;void test1()
{//管理对象int* ptr4 = new int;int* ptr5 = new int(3);delete ptr4;delete ptr5;//管理对象数组int* ptr6 = new int[3];delete[] ptr6;
}int main()
{test1;return 0;
}

具体分析如下: 

 2.2.2自定义类型内存管理

既然new和delete与C中动态内存管理差不多,那为什么还要设计这两个运算符呢?C++中引入了自定义类型,为自定义类型开辟空间也算实例化的一种,但使用malloc等函数无法在开辟内存时调用构造初始化,所以在C++中引入new和delete来动态管理自定义类型空间。

new和delete更抽象的来说更像一种运算符重载,new将开辟空间与调用构造封装在一起,而delete则将空间销毁与析构封装在一起。下面以Stack为例进一步理解:

#include<iostream>using namespace std;template<class T>
class Stack
{
public:Stack(int n = 4):_arr(new T[n]),_size(0),_capacity(0){cout << "Stack(int)" << endl;}~Stack(){if (_size != 0){free(_arr);_arr = nullptr;_size = _capacity = 0;cout << "~Stack()" << endl;}}void Push(T x){_arr[_size] = x;++_size;}private:T* _arr;int _size;int _capacity;
};void test2()
{Stack<int>* s1 = new Stack<int>;(*s1).Push(1);(*s1).Push(2);(*s1).Push(3);delete s1;
}int main()
{test2();return 0;
}

下面利用图解理解:

遇见对象中再开空间的情况:new会优先给对象开空间,然后调用构造函数给对象成员初始化;delete销毁时会优先调用析构函数销毁对象中的资源,随后再销毁对象。

2.2.3 delete与delete[ ]

在C++中new与new[ ],delete与delete[ ]有着不同重载。其中一方面是new[ ]与delete[ ]要开辟多次空间以及调用多次对象构造与析构,实现方法不同;另一方面new[ ]会在开辟所需内存外,另外留出部分空间来记录所开辟的大小参数,方便delete[ ]来正确销毁空间大小,相应的delete[ ]会从记录空间销毁,而delete则是直接从指针起始位置开始销毁。

所以这里new与delete,new[ ]与delete[ ]要匹配使用。

http://www.xdnf.cn/news/386875.html

相关文章:

  • 互联网大厂Java求职面试实战:Spring Boot到微服务的技术问答解析
  • 《Redis应用实例》学习笔记,第二章:缓存二进制数据
  • “多端多接口多向传导”空战数据链体系——从异构融合架构到抗毁弹性网络的系统性设计
  • [工具]B站缓存工具箱 (By 郭逍遥)
  • MyBatis源码解读5(3.1、缓存简介)
  • 常见的排序算法(Java版)简单易懂好上手!!
  • path环境变量满了如何处理,分割 PATH 到 Path1 和 Path2
  • Java高频面试之并发编程-15
  • ES常识5:主分词器、子字段分词器
  • 嵌入式硬件篇---CAN
  • 【Mac 从 0 到 1 保姆级配置教程 12】- 安装配置万能的编辑器 VSCode 以及常用插件
  • Spring框架(2)---AOP
  • 鱼眼相机生成-BEV鸟瞰图-入门教程
  • Nginx yum 安装
  • 从数据处理到模型训练:深度解析 Python 中的数据结构与操作实践
  • Unity3D仿星露谷物语开发42之粒子系统
  • 使用FastAPI和React以及MongoDB构建全栈Web应用05 FastAPI快速入门
  • Problem C: 异常1
  • 在Java项目中实现本地语音识别与热点检测,并集成阿里云智能语音服务(优化版)
  • 基于Qt的app开发第七天
  • leetcode 454. 4Sum II
  • 【数据库知识】Mysql进阶-高可用MHA(Master High Availability)方案
  • Git标签
  • 多模态大语言模型arxiv论文略读(六十八)
  • 各类有关NBA数据统计数据集大合集
  • Hibernate 性能优化:告别慢查询,提升数据库访问性能
  • 《Effective Python》第1章 Pythonic 思维详解——item03-05
  • C# 高效处理海量数据:解决嵌套并行的性能陷阱
  • 深入理解 JavaScript 中的 FileReader API:从理论到实践
  • React 从零到一执行原理 (2025 最新版)