new和delete到底做了什么?

在C++之中,进行内存动态分配之时,new和delete是我们每一个人都会用到的。但是new和delete到底做了些什么呢?在我看了这么多书之后,发现很少有书去介绍这方面的知识,,即使有也是仅仅的说下new和delete的实现。而我要的不仅仅是这些东西。我想明白,他到底对内存做了那些手脚。好,下面我就从头慢慢说一下我的观点,一家之言,欢迎拍砖。

1 了解一种指针行为

Code:

这个程序我连测试了4个编译器,都没有错误发生,是的,它也不会发生错误。因为它从语法上并没有什么错误。那我为什么要把他列出来呢?因为它曾一直是我困惑的一个问题。我们再来看一下另一个程序,看他们两个有什么区别。

Code:

哇。。可能有同学开始嘲笑我了。这两个程序的区别不是很明显吗?一个申请了空间,一个没申请空间。哈,也是。。不过第一个没有申请空间,我们为他赋值了,为什么就能成功呢?关键就在这里了。为什么呢?我曾一直迷糊,直到现在心中也没有一个标准的答案。目前我对他的解释是:

当我们定义了一个指针p后,由于我们并没有为他初始化,故此刻指针p指向了一个随即的空间。之后我们对p的解引用操作,即赋值操作,皆是对哪个未定义空间的操作。然而若是我们在定义p时就为他初始化为0,那么之后的解引用行为将会出错。

这是我目前的解释。在未得到高手认可之前,心里总有些不踏实。

好的,现在我们再对第一个程序提出另一个问题,现在p指向的随即内存是栈上的呢,还是堆上的呢?好,对此我进行一项测试,在*p = 5;之后我加上这一句:

Code:

deletep;

然后在输出p中的内容。经过测试之后,C-Free,Code::Blocks 放行通过。VS2008,GCC却把我拒之门外了。这是怎么回事呢?是C-Free,Code::Blocks 改变了*p的解释方式。还是他们并未兼顾到C++这项标准(不能delete 一个栈空间,不知道是不是标准,暂且这样说吧)。不得而知,甚至我根本无法知道p目前指向的栈空间,还是堆空间。这些东西一直困扰着我。希望有朋友能帮我解决了,了却心中一憾事。。;-)。

2 我们去了解第二个程序

稍微修改之后是这样的:

Code:

程序的结果是一个随机值,又在我的意料之外了。我认为:delete p; 之后p仍是指向原来的那块内存空间,这个我几乎是肯定的。p是没有变的。虽说已经delete p;了,即现在p已经变成了一个野指针。但我们的程序中在释放p之后,并没有申请空间啊。。p所指向的那块内存值并不应该改变,所以我认为输出的值应该是5.然而经过4个编译器的测试之后,结果如下:

VS2008 ,GCC 输出结果为随机值

C-Free , Code::Blocks 输出结果为0

出现了这样的结果,奇怪之余。我认为原因如下:

编译器做了手脚.,这应该也是delete的内幕,而delete在实现上调用了,free(),应该说是free()的内幕了。我猜想它是这样做的。一旦释放了某个空间之后,VS2008 ,GCC 就给这个内存空间设一个随机值,而C-Free , Code::Blocks 则是将这段内存空间初始化为0.并告诉编译器这个内存我不要了,你可以随便分配了,相反我们new一个空间或是malloc一个空间则是告诉编译器这个内存空间从现在开始是我的了,你不能再进行支配了。呵呵。。这只是一个表面的理解,更深的就牵涉到操作系统里内存的分配了。这里就不再多说了。想了解的同学,可以拿出操作系统书,结合这里提出的问题思考一下就会明白的。

这里我要说的就是其实在释放一段内存空间之时,我认为那块内存并没有改变什么,它还在它原来的地方,或者只是编译器为他写进了一个值而已。即使有复杂的地方,那些事牵涉到操作系统里内存空间的分配与释放,这就是操作系统的事情了。有些朋友在理解上可能把释放空间复杂化或是错化了,可能他们把理解释放空间理解成和链表中的结点删除了。。呵呵。我曾经就有过这种想法,而我现在的理解就是上面我所说的。如果不同见解,欢迎就此讨论哈。

3 不甘心之free()测试

我想看看各个编译器对free()的理解,于是就有下面程序进行了一个小测试:

Code:

结果还是有些出乎意料。就是GCC了。它对delete的解释是一个随机值,而对free()的解释是0.其他编译器解释前后均一致。确实有些不解了。不过也不打算在对此做些深究了。。

4 另一种令你吃惊的行为

Code:

输出结果:

q对应内存单元的值: 6

p对应内存单元的值: 6

吃惊吧,我们已经把p对应的内存单元释放了,而后为q申请了一个内存空间,并赋值为6.结果p对应的内存单元值也成6了。

开始对此我的解释是:p对应的那块内存单元在内存分配时应该是优先级最高的。所以开始p申请时,p获得了那块内存单元。而后p释放之后,p对应那块内存单元又被放到相应的位置,优先级仍是最高的。故q申请时又获得了那块内存单元。因而改变了*p的值也就改变了*q的值。但是测试了以下程序后,我不再坚持这种观点了。我开始怀疑编译器的更大的“黑幕”了。

Code:

这个程序我仅仅是输出了一下p释放后,q申请之前p所指向内存单元的值。但是这样就改变了整个程序的结果。

输出结果:

吃惊吧。。q之前的一个对p的解引用到底做了什么呢?它改变了什么呢?又是一个不得而知的行为,这里引用Lippman的一句话是

“除了瞎猜之外,唯一能够正确回答的办法,就是知道正确答案”

(*^__^*) 嘻嘻……

总之,你永远无法知道C++到底背着你做了多少事情,总感觉这里是一个无底的黑洞。你想进去寻找另一处的光明,那绝是一种未知行为。;-)

旅行,有一种苍凉,“浮云游子意,落日故人情”,

new和delete到底做了什么?

相关文章:

你感兴趣的文章:

标签云: