IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++ 内存管理 -> 正文阅读

[C++知识库]c++ 内存管理

内存分配方式

首先看一下内存是如何分配使用的
在这里插入图片描述

  1. 静态存储区域分配。
    内存在程序编译的时候就已经分配好了,也就是说已经编过地址了
  2. 在堆栈上分配 。
    在函数执行期间,函数内局部变量(包括形参)的存储单元都创建在堆栈上,函数结束的时候这些存储单元自动释放。这种内存分配方式的效率很高,一般不存在失败的风险,但是分配的内存容量有限,堆的容量很小,是兆(M)级别的,容易发生栈溢出。
  3. 在堆上分配。
    也叫做动态内存分配,程序在运行期间用malloc或new申请任意数量的内存,堆的容量很大,是G级别的,(比如递归时容易发生栈溢出,就可以在堆上模拟实现栈完成递归)。程序员自己决定释放内存的时间(使用free或delete)。动态内存的生存时间由程序员决定,使用非常灵活,但是也非常容易出错。
  4. 使用内存分配的一般原则是:
    如果使用堆栈和静态存储就能满足应用要求,就不要使用动态存储。这是因为在堆上动态分配内存需要其他的额外开销。主要原因如下。
    4.1 在堆上分配内存时,需要找到符合要求的空闲的连续的字节内存块。特别是在经过多次内存分配之后,堆会变得“千疮百孔”,出现大量的闲散的内存碎片,此时可能需要首先进行碎片合并,然后才能分配成功,在这种情况下内存分配需要很长时间。
    4.2如果动态分配失败,需要检查返回值或者捕获异常(try catch),这也需要额外的开销。
    4.3动态创建的对象可能被删除多次(比如在这个程序前一部分你已经释放过内存了,但是后来你又忘记了,就又释放了一次),甚至在删除后还会继续使用(还是前面那个例子,已经释放后还要继续使用那块内存空间)。如果发生这种情况,运行时会发生错误,或者出现“内存泄漏”的现象,这些问题是很难避免的,当代码量很大的时候,很容易出现这些意外情况。
  5. 代码段和数据段的区别和联系
    5.1 代码段:代码段就是程序中的可执行部分,直观理解代码段就是函数堆积组成的。
    5.2 数据段:(也被称为数据区、静态数据区、静态区):数据段就是程序中的数据,直观理解就是C语言程序中的全局变量。(注意:全局变量才算是程序的数据,局部变量不算程序的数据,只能算是函数的数据)

c语言中的内存管理方式

1. malloc/realloc/calloc

1.1 malloc
在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址

int* p=(int*)malloc(sizeof(int)*10);//开辟40个字节的空间

1.2 realloc
在已有的基础上对内存空间进行调整,也就是进行扩容

int* p=(int*)malloc(40);//先开辟一块40个字节的空间
 p=(int*)realloc (p,400);//再把这块空间扩容到400个字节

1.3 calloc
和malloc的作用相识,开辟好空间之后会把这块空间的数值初始化成0

int* a = (int*)calloc(10, sizeof(int));//开辟一块40个字节的空间,并且把她们初始化成0

2.free

释放空间,为了避免野指针,free后要再把指针置成空(NULL)

free(p);//把空间还给操作系统
p=NULL://把指针置成null,防止再次访问

c++中的内存管理方式

1. new/delete

new是c++新引入的操作符,他的主要作用和malloc他们几个一样,都是动态开辟空间,但是new又做了一点小改进。

  • 对于自定义类型,如果使用new,会开辟空间+调用构造函数初始化。
  • 对于内置类型,如果使用new,和malloc的作用一样,只会开辟空间。

delete是c++新引入的操作符,他的主要作用和free相似,但是delete不仅会释放空间,还会自动调用析构函数。

  • 对于自定义类型,如果使用delete,会释放空间+调用析构函数。
  • 对于内置类型,如果使用delete,和free的作用一样,只会释放空间。

内置类型的例子

void test1()
{
	int* p1 = new int;
	//new一个int大小(4个字节)的空间
	int* p2 = new int(10);
	//new一个int大小(4个字节)的空间,并且初始化成10
	int* p3 = new int[10];
	//new一个40个字节的空间(10个int类型)
	int* p4 = new int[]{ 1,2,3,4,5 };//这里大括号里是数组个数,可以省略,就像初始化数组一样
	//new一个40个字节的空间的大小,并且初始化他们


	delete p1;
	delete p2;
	delete[]p3;
	delete[]p4;

}

代码运行结果如下:
在这里插入图片描述


自定义类型的例子

class Test
{
public:
	Test()
	{
		cout << "构造函数"<<"  " << this << endl;
	};
	~Test()
	{
		cout << "析构函数" << "  "<<this << endl;
	}
private:
	int x;
};

void test2()
{
	Test* p1 = new Test;
	Test* p2 = new Test[10];
	delete p1;
	delete []p2;

}

代码运行结果如下:
可以看出用new开辟空间,不仅会开辟空间,还会自动调用构造函数和析构函数。
在这里插入图片描述

在这里插入图片描述
总结:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。

2.operator new/operator delete

operator new /operator delete是系统提供的全局函数,而new/delete是一种操作符。
new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。


operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。operator new本质是封装了malloc。operator delete本质是封装了free。
??注意:operator new/operator delete不是对new /delete的重载,他们就是独立存在的库函数。

说了这么多,用一句话总结一下:
当你用new开辟空间的时候,new会去调用oparator new函数,然后operator new又会去调用malloc开辟空间。

  • new=operator new+构造函数
  • operator new=malloc+失败了抛出异常
    对于delete也是同理
  • delete=operator delete+析构函数
  • operator delete=free

画个图理解一下
在这里插入图片描述

在这里插入图片描述

new/delete实现原理

内置类型


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


自定义类型

new
调用operator new函数申请空间 在申请的空间上执行构造函数,完成对象的构造
delete
在空间上执行析构函数,完成对象中资源的清理工作 调用operator delete函数释放对象的空间
new T[N]
调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请 在申请的空间上执行N次构造函数
delete[ ]
在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:12  更:2022-10-08 20:26:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 9:10:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码