当前位置: 首页 > 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[ ]要匹配使用。

相关文章:

  • ES 面试题系列「二」
  • HTML难点小记:一些简单标签的使用逻辑和实用化
  • 49.EFT测试与静电测试环境和干扰特征分析
  • RS485和RS232 通信配置
  • 【Linux高级全栈开发】2.1高性能网络-网络编程——2.1.1 网络IO与IO多路复用——select/poll/epoll
  • Kubernetes排错(十四):Pod状态异常排查手册
  • 每日脚本 5.11 - 进制转换和ascii字符
  • Lambda表达式能用在哪些场景?
  • libcurl简单使用
  • TeledyneLeCroy在OFC2025 EA展台上展示了其400G/800G的全包围的测试解决方案,满足了UEC联盟和UALINK联盟的技术需求
  • [Java][Leetcode simple]26. 删除有序数组中的重复项
  • 欧拉路与欧拉回路(模板)
  • Java学习笔记(对象)
  • 图形硬件系统
  • FPGA生成随机数的方法
  • InnoDB引擎
  • 红外遥控键
  • RDD转换操作中的 关于数据分区coalesce 和 repartition 的区别
  • 轻量服务器与宝塔
  • 查看YOLO版本的三种方法
  • 尊严的代价:新加坡福利体系下的价值困境
  • 欧元区财长会讨论国际形势及应对美国关税政策
  • 郑州通报“夜市摊贩收取香烟交给城管”:涉事人员停职调查
  • 巴防空系统击落印度无人机,印称巴方违反停火协议
  • 习近平结束对俄罗斯国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典回到北京
  • 肖峰读《从塞北到西域》︱拉铁摩尔的骆驼