作者:几冬雪来
时间:2023年5月14日
内容:C++内存管理讲解
目录
前言:
1.类的对象(收尾):
1.友元函数:
2.内部类:
3.匿名对象:
4.优化:
2.C++的动态内存管理:
1.动态内存管理的管理方式(malloc,realloc,calloc,free):
2.new和delete内置操作符:
结尾:
前言:
通过这篇博客的主题可以看出,在这一篇博客我们将讲解一个新的知识点,也就是我们的内存管理的模块,而在这之前我们要将我们之前的类和对象的内容进行收尾。
1.类的对象(收尾):
在这里在学习新知识之前,我们需要将我们的旧知识,也就是类和对象板块的知识做一个收尾的工作。
1.友元函数:
在这里我们的友元函数主要就是突破类的限制,突破C++中类的封装。
在我们的类外面有时候我们是需要用对象去访问我们类的成员的。
在这里经典的就是我们的流插入和流提取操作符的重载。
因为流插入和流提取的代码如果我们写在类中变成成员函数,它们就会出现抢占位置的操作,抢占左操作数。
但是这里其实我们在C++中并不是经常使用友元函数,它提供了遍历,但是增加了偶合,
这里还有友元类。
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
并且友元函数还许多的规定在:
这里我们就对友元有个大概的了解即可。
2.内部类:
接下来我们学习的知识点叫做内部类。
在这里我们简单的将内部类的代码进行书写,并且计算它的大小。
从结果上来看大小为4,那么这里的大小是怎么样进行计算的呢?
首先用到上一篇博客的知识,我们的k并没有存到对象里面,所以没有参与计算。
而这里肯定要计算我们的h的大小,并且在这里A里面没有我们b对象,所以我们也没有去计算b的大小。
除非我们用B类在A类中创建对象才有计算b的大小。
它并没有占空间,因为它只是声明。
并且在调用的时候我们也要进行修改。
当然在这里我们的内部类也受访问限定符的限制,也就是受到公有和私有的限制。
同时在这里我们的内部类是外部类的友元。
只不过在C++中我们并不经常使用内部类,我们在外部类定义的东西,内部类可以访问,外部类也可以访问。
3.匿名对象:
接下来就是来讲解我们的匿名对象。
在这里我们先将其写法写出来。
这里就是我们的有名对象和匿名对象。
当然我们的调用函数也可以使用匿名对象来对其进行书写。
这里我们上面的那种方式就是有名函数,下面的书写方式就是匿名对象的形式。
这里要注意匿名对象只用于调用一次,如果调用多次函数要用有名对象。
并且我们的匿名对象即用即销毁。
这里我们将全部的代码拿出来看看。
在这里如果要传参的话,我们也可以在匿名对象处进行传参的操作,这样我们才能继续使用我们的匿名对象的操作。
同样的这里我们也可以对命名对象进行引用,不过引用命名对象的时候要注意一些点。
首先在这里,我们不能通过这种形式用ra去访问我们的匿名对象。
这是因为我们的匿名对象和临时对象类似,具有常性。
但是在这里我们只要在引用的前面加入我们的静态const就可以进行引用。
并且这里并不是出现野引用,这里的const引用延长了对象的生命周期,生命周期在当前函数的局部域。
这里的匿名对象的创建没有个数的限制。
4.优化:
在这里我们就直接将代码给写出来。
在这里,我们的下面的方法会从两个构造优化为构造。
因为它们是在同一行进行的这两种行为,所以会被优化,而且上面的那种方法因为并不是同一行,而是连续两行的执行,所以并不会被优化。
从这里我们也可以看出来优化所带来的便利。
在这里下面的方法我们要多调用一次构造,并且还要执行赋值的操作。
2.C++的动态内存管理:
在我们的C++中,有几类的数据,我们将它们称为:
局部数据;静态数据和全局数据;常态数据;动态申请数据。
并且在这里我们要对每个数据的存放空间进行划分区域。
并且这块空间被我们称为进程地址空间。
接下来我们就通过答题来了解我们这些数据。
在这里我们的第一个在全局所以它在——静态区。
第二个是静态的所以它在——静态区。
第三个也是静态的在——静态区。
接下来我们第四个是局部变量所以在——栈。
第五个是一个数组所以也在——栈。
接下来我们来再讲解6道题。
在这里我们的char2毋庸置疑在——栈。
*char2为数组首元素的地址,在这里数组首元素的地址也是在——栈。
pchar3为指针虽然被const修饰,但是实际上它是指针所以在——栈。
*pchar3是对pchar3进行解引用,里面的数据被const修饰所以在——常量区。
ptr1为指针,在——栈。
*ptr1是对ptr1的解引用,里面ptr1的内容是通过malloc得到的,所以它在——堆。
在这里我们也可以去计算它们的大小。
1.动态内存管理的管理方式(malloc,realloc,calloc,free):
在这里我们出一个问题。
在这里如果我们对p3进行释放的话,这里需要对p2进行释放?
学过C语言的我们应该知道,这里分两种情况一种是原地扩容一种是异地扩容,原地扩容的话,这里我们就是在p2的基础上对其进行扩容操作。
而异地扩容的话在这里,我们要先找到合适的空间,然后将p2的内容拷贝过去,接下来将p2释放掉。
因此上面的要对p2进行释放,下面的代码不需要。
2.new和delete内置操作符:
接下来我们要在这里我们上面的代码可以通过malloc来进行内存空间的开辟,这种用法是C语言我们常用的用法。
而且在C++中我们不仅依旧可以这样使用,我们还引入了新的操作符来完成我们上面的步骤。
在这里我们使用新的操作符new来完成我们的操作。
并且new代码的书写形式也是十分的便捷,就是new+类型即可。
同样的我们的new也可以对数组进行。
这里和C语言malloc后释放使用free不同,我们的new要进行释放的话就需要用到我们和new配套的另一个操作符delete了。
而且我们创建空间之后肯定要初始化的,这里我们的C语言就不讲了,来讲讲我们的new操作符的初始化方式。
在那之前我们先来讲解一个new操作符要大致知道的点。
在这里我们要注意,像我们下面的代码有讲过,就是申请10个int的数组。
但是上面的代码并不是申请数组,而是初始化。
那这里我们的数组初始化又是怎么样的呢?
并且和我们的C语言一样,这里后面没有被初始化的空间我们默认存放的是0。
那么有人就在这里问了,我们的new创建出来是为了什么呢?上面的写法都可以书写,为什么要有new操作符呢?
这里我们就引用以前的一段代码来分析一下。
在这里我们左边的代码是我们数据结构时候链表的代码。
在那个时候我们要书写的话是用到右边上面的代码进行书写的。
但是在我们的new到来之后,我们就可以使用下面的这种书写方法,它可以开空间并且调用构造函数的初始化,这就是我们new真正被创建出来的意义。
结尾:
到这里我们的C++板块的类和对象到这里就正式的结束了,接下来我们要进行C++又一大板块的学习了,在学习新知识的同时,我们也不能忘记现有的就知识要多复习。最后希望这篇博客能给大家带来帮助。