windows系统使用c++实现自动垃圾回收的小demo

  自从疫情爆发以来,过得挺充实,天天学习,乐此不疲。  可惜就是把实习工作给戳脱了,不然就完美。哈哈哈,不过这段时间的收获还是很足很足的,朕心甚悦!!  这段时间主要在加强对c++ 的学习,练习了很多小的demo,通过对相对底层语言的学习实践,达到掌握很多高层知识的目的(事实上,很多知识记了又忘,忘了又记,恶性循环的原因在于理解的深度不够)。

  接触了java三年多,大部分知识自学,一直听说什么什么垃圾回收,内存模型啥啥啥的,也看过很多相关的资源,始终是透着一层薄薄的窗户纸,若隐若现,很不痛快。这个小demo的目的就在于,揭开它神秘的面纱,看看其庐山真貌。此外,也涉及到对Java相关知识的理解,如为什么所有类都是Object的子类为什么类加载器机制为双亲委派模型为什么java中去除了指针?  也涉及到一些对跨平台的理解,如: 为什么java语言跨平台如此重要? 希望能够帮到有需要学习的小伙伴。

  首先,通过查阅资料,得知如下的信息:

         1.java中的垃圾回收机制,使用标记清除法,即从内存中的所有根对象进行遍历,设置其可达状态,对不可达的对象释放其内存。

        2.遍历操作,数据量小还好,如果数据量巨多,同时,gc调用频繁,回收率很低的话,则整体的性价比太低。为了解决这个问题,通过 代际回收 来解决。 即所谓的 新生代,老年代,持久代。

       3.要进行垃圾回收,所有的对象必须j派生于一个公共的类。

  接下来开撸:

定义公共祖先类,相当于Java的Object

定义容器,保存对象的地址:

实现祖先类中的关键方法:

接着,定义一些测试子类:

最后,为了较为优雅的实现 对根对象的维护,我采用了一个对象工厂来进行维护,所有的对象均由工厂生成(因为我暂时找不到更好的抽象模拟根对象,此外,这个实现不是线程安全的)。

测试代码:

  以上,就是本次小demo的核心结构,和关键代码。现在,来回答本文一开始提出的相关问题。

1.为什么所有类都要派生至一个祖先类?

    答:一方面,统一接口规范; 最根本原因在于,可以隐式实现对象的收集! (此外,我认为跟子类代码偏移之类啥的关系不大。因为一个无状态指针完全可以 指定为任意类型的指针,举个例子: void* a;  a =(void*)(new int(1))  是可以的,a=(void*)(new long(1))  也是可以的。)。

2.为什么java中需要使用双亲委派机制?

   答:从第一问可知,祖先类的唯一性十分重要,因此Object的是必须首先要保证唯一性的,这涉及到java的根源,之后我在实现jvm的小demo中,也会进一步验证。

3.为什么java中去除了指针?

  答:在c++中,我们的对象实际上有两种生成方式,其一为 "Object o;"  注意,这跟java很很大差别,它实际上是栈分配的内存,在代码出栈的时候,该内存会被回收。  所谓的出栈,入栈,其标识为代码块,即{ code ...} 部分。其二为"Object* o=new Object();",这个跟java就是一样的了,=左边我们称之为 左值,它是一个指针,指向new Object()的首地址,右值为堆分配的内存,它代表了这个对象在内存中的映像,它的表现是一个地址。

       栈分配的对象,在出栈时会自动回收,这本该是一个好事,但是考虑一种情况,如果我要跨域 使用对象呢??

       堆分配的内存,满足了跨域使用的要求,但是它不会自动释放的(当然,程序结束后,会释放掉)。 我们当然可以选择手动释放,但是手动释放会遇到一些问题,如: 跨域使用的对象,我何时删除?  当程序足够大,对象足够多,这将是一个可怕的工程,任何一个不当的操作都会导致灾难!  当然了,也可以粗暴的选择不释放,最终结果就是内存耗尽,系统健全的话,程序异常结束;系统不健全的话,导致重启。非常不幸的是,我还就曾经导致了这样的问题,至今回想起来还心有余悸。我的笔记本是舍不得的,还好是东家的老台式。

       为了兼容二者吧,java就引入了真命天子 ——gc,就规定了,所有的内存均由 垃圾回收器进行回收,即不是栈自动回收,也不是手动回收。 所谓没有对比就没有伤害,没了栈分配变量,对分配变量指针自然也就不叫了,我是这样理解的。还没去查资料,权当自娱自乐吧。

4.为什么跨平台如此重要?

    答: 这是我在较为系统的使用c++进行编码实践的时候面临的第一大问题,网上很多的例子使用的都是linux进行实现,linux与windows的一些api存在差别,而恰好,这些api对我来说又是十分关键的。 如线程: linux的pthread,windows的原生api,文件操作的区别,socket套接字的区别。。。   我才猛然回想起,好像我不是菜鸟啊?  接触编程也挺久了,以前java感觉用的飞起,不论是Linux开发部署也好,windows开发部署也好! 

     此时,脑海中回想起 课桌上,某老师跟我们说java是跨平台的语言,xxxxxxx。。 嗯,明白了,跨平台,真不只是说说而已,其中的酸楚只有趟过坑的人才会对 ”跨平台“,爱得深沉,爱的热烈。   想想一个APP,需要同时开发多个端的痛苦吧,ios,android,h5,小程序等等,最操蛋的是,它们明明功能都是一样的,样的,的。。。。。   


附上这个小demo的github地址,所有代码均在里面,有小伙伴感兴趣的也可以留言讨论哦!

地址

另外,这篇文章写得既不系统,也不详细。  超级推荐先看一下这篇文章,本demo可以说完全基于它进行实现(原帖时间过于久远,我找他文中的资源已经找不到了。):

自己动手,用C++实现垃圾回收系统

我的开发环境是:windows10 + mingw64 + clion + cmake

发布了340 篇原创文章 · 获赞 159 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_36285943/article/details/104704359
今日推荐