由于对象a是个局部对象,因此当函数对象func结束后,局部对象a也就被删除了。由于对象a消失了,所以Func()函数返回的其实是一个并不存在的对象的别名。
用这个不存在的对象来调用该对象的函数get()。该函数会返回一个并不存在的对象的x成员。因此输出一个随机数。
如果这样,那输出就是23,为什么?
因为去掉引用符号后,返回方式变成了按值返回,而按值返回又会调用复制构造函数,复制一个对象a的副本,然后将这个副本再赋给r,r就是这个对象a的副本的别名。
下面举个例子说明这个:
VC6.0下输出结果:
跳转到func函数中!
调用构造函数创建一个对象
对象a的地址0012FF00
执行复制构造函数创建一个对象
执行析构函数
对象a的副本的地址:0012FF6C
23
执行析构函数!
看到这个结果相信会明白不少东西。但是与此同时,这里有个问题:
为什么对象a的副本的生命会一直持续到main函数结束呢?(上面最后一句输出:执行析构函数!就是对象a的副本的析构,所以有必要怀疑一下他的生命周期!)
这是因为对于引用而言,如果引用的是一个临时变量,那么这个临时变量的生存期会不少于这个引用的生存期。
(参见c++标准[class.temporary])
也就是说,直到main函数结束时,引用r的生存期结束,r所引用的临时变量的生存期才结束,由于r所引用的是一个对象,因此这时才会调用它的析构函数来释放内存。
PS;
顺便说一下,指针是没有这个特性的,假如将对象a的副本的地址赋给一个指针,那么在func函数返回对象a的副本的时候,就可以析构这个对象a的副本。
输出结果如下:
跳转到func函数中!
调用构造函数创建一个对象
对象a的地址0012FF0C
执行复制构造函数创建一个对象
执行析构函数
执行析构函数
对象a的副本的地址:0012FF78
23
分析:连续执行了两次析构函数,将对象a和他的副本所占用的内存全部释放掉了。
但是我们确实看到了get函数输出了对象a的副本的x成员为23
于此我们也知道对象a的副本已经被删除了啊,已经析构过了啊。为什么这里又输出了他的成员x的值呢?
::这是因为析构函数调用并析构某个对象后,只是告诉编译器这一块内存不再为某个对象独占了,你可以访问它,别的对象或者变量也可以访问它并使用该内存区域存储他们的数据,但是在他们使用之前,存放在该内存区域中的数据并没有删除,因此使用指针来访问该区域仍然能够得到未被修改的x的值。