20210127关于golang的nil(2)深入思考c 的delete某个变量与golang里给某个变量赋nil之间的相同点与不同点 - ziyouzy/2021blog GitHub Wiki

首先是c++,请看文章:
http://c.biancheng.net/view/206.html
总结:delete删除的是new出来的东西,也就是内存块,而不会删除int p的p,p是个指针数据类型,作用域生命周期结束会被自动释放*
同时他的数据结构是这样的如(伪代码):

int* p =new int(3)

p是个指针类型,其值是个指向一块堆内存的指针,这个堆内存里储存了值为3的整型
这个堆整型没有变量名,只能同过p这个指针来调用
同时我也可以定义一个q指针,让他也指向同一块堆内存。
于是在语法上,我无论是delete(p)还是delete(q)都会删除这块对内存,而p和q这两个变量则均不会被删除,等待生命周期的结束一并释放
这中“手动模式”就是c++的内存回收模式

然而到了java,golang,c#中,内存回收机制不再手动,而采用了自动的模式,也就是“GC”
GC这一“另一种”内存管理机制其中有两个特点方法最开始的这里探讨:
1.不再使用new来实现一个堆类的变量,无论是那种数据类型,其初始化的方式和简单数据类型并无区别,这是语言的设计这对语法进行的意思封装
2.不再提供delete这种“手动删除”堆内数据的语法接口,而让堆内数据和其所属其他值类型数据(其实就是引用类型与值类型的区别),一同基于作用域与生命周期原则销毁
值类型在某个循环末尾的“}”或某个函数末尾的“}”位置被销毁,同一个位置,如果该生命周期存在引用类型(概念上等同于c++的堆内数据),将被GC销毁

c++与golang等的内存管理机制存在着巨大区别,而区别的核心其实是在于某个变量储存了“指向”某个堆内存内数据,的这座类似桥梁的“结构”或者说是“模式”
两者都拥有这两的模式,可以说它是内存管理的基石

回过头来,GC其实是为了完善c++而设计的,但是似乎其并没有消灭问题,而是把一钟类型的问题转换成了另一种类型的问题:
c++手动管理内存存在两个问题:
1.是程序员在new了一个东西后很可能会忘记delete他
2.是程序员虽然没有忘记delete,但是忘记了其他的作用域有指针依然指向着被delete的堆数据
3.不涉及delete操作,程序员可能会不小心修改了堆内数据的值
前者造成内存泄漏,没什么可说的,是低级问题
而后者就不同了,如果另一个作用域调用了已经被delete的堆,程序会直接崩溃
从而让其他作用域里指向他的“数据出口”拿到错误的数值,让程序计算错误,且不好排查

于是人类设计了GC:
而GC存在的结果是:
1.消灭了上面1的问题
2.没有消灭上面2的问题,而改变了他所导致问题的样子:也就是程序不会崩溃,而可能会造成内存泄漏(准确的说是作用域泄漏)
补充一点,作用域泄漏的原因可能有好几个,如chan的阻塞,conn.Read的阻塞,for循环的阻塞,以及这个作用域内有被其他作用域指向的引用类型变量,等,更重要的是这类作用域泄漏问题同样存在于c++中
3.没有消灭上面3的问题,问题原封不动的需要程序员自己解决

下一篇会最终探讨为何GC机制会优于前者

而在这我们回到正题:
c++的delete清除的是堆内的变量,golang中=nil是将一个应用类型和他所指向的内存空间“解引用”,从而为gc自动回收做好准备
这就是两者之间的区别