随笔 - 2  文章 - 17  trackbacks - 0
<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(1)

随笔档案(2)

搜索

  •  

最新评论

阅读排行榜

评论排行榜

一会儿再把分析转过来。



#include
<iostream>
using namespace std;
class A
{
public:
    A(
int n):val(n){}
protected:
   
int val;
};
class B:public A
{
public:
    B(
int n):A(n)
    {
        pB
=(n>0? new B(n-1):0);
    }
   
~B(){delete pB;}
   
void Display()
    {
        cout
<< val << endl;
       
if(pB!=0)pB->Display();
    }
private:
    B
*pB;
};
int main()
{
    B b(
4);
    b.Display();
   
return 0;
}



==================================================================




程序的运行结果是:
                4
                3
                2
                1
                0



===================================================================

tangshuiling 给出的解释:

B(int n):A(n)
{
pB=(n>0? new B(n-1):0);
}

B b(4); /**用 4 初始化 A 类成员 val, val=4*/
/**此时 n=4 满足大于 0 的条件,调用 new B(3),同时栈要维护现场,
存储 val=4,pb=new B(3) 产生的对象地址设为 pb1 以及函数的下个语句
地址,此时是‘}’就相当于return。
*/

依次类推栈中保存了 (val=4,pb1) (val=3,pb2) (val=2,pb3) (val=1,pb4) 最后 val=0, pb=0
,遇到‘}’符号本应该 return 的,但由于此时栈不空,因此还必须做出栈的操作,因此,最后出栈是:val=4, pb1。

b.Display();
调用此句,显然此时 val=4,pb=pb1 pb1->display(); 此时 val 应该是
等于3,pb1=new B(3); 依次类推:

pb2->display(); val=2
pb3->display(); val=1
pb4->display(); val=0

此时 pb=0,不满足调用条件直接 return 了

from:http://topic.csdn.net/u/20090109/00/67841ac5-3197-4842-b0e9-ce3c6aa962d9.html
posted on 2009-01-12 09:34 末檐儿@了修 阅读(1458) 评论(16)  编辑 收藏 引用

FeedBack:
# re: 一道有意思的题目,大家看看输出:) [未登录] 2009-01-12 12:33 dd
在创建对象b后,b的成员变量pB是指向的B(3)这个对象的地址,那么调用Display,不就是显示4和3吗?  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:) [未登录] 2009-01-12 12:40 dd
Display也是一个递归函数嘛,b这个对象指向的是B(4)这个对象,这个对象的成员pb指象B(3)这个对象,在调用Display的时候,又会调用B(3)这个对象的Display。依此类推,直到pb为NULL。  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-12 13:38 yu
这里的解释是否有不合理的地方?

"依次类推栈中保存了 (val=4,pb1) (val=3,pb2) (val=2,pb3) (val=1,pb4) 最后 val=0, pb=0
,遇到‘}’符号本应该 return 的,但由于此时栈不空,因此还必须做出栈的操作,因此,最后出栈是:val=4, pb1。"


这里为什么栈不为空就必须要做出出栈的操作?最后出栈的不是应该最后输出才对?  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-12 14:02 了修
个人认为:这里的出栈,是相对于return来说的,pb 和 val 逐次回归。
关键看自己怎么理解了

@yu
  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-12 15:23 ss
跟现场保护什么事?
这不就像建了个链表,一顺打印出节点值吗。  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-12 17:42 GameOgre
很简单的题目,按照基本语义就很容易理解,非要从低层机制去解释,实在有点过分了,正如楼上所说,就是一个简单的链表啊。是想说递归机制吗?  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-12 21:58 bneliao
这个会有内存泄露的!!
除了第一个”对象“是在栈上实现之外,后面它指针指向的对象都是通过new的方式在堆上实现,而c++似乎没有删除堆上指针指向的对象能力(这个”堆上“资源的回收可以用gc来实现);其实这个递归实现有点像函数式编程里的”闭包“实现。
有错误,请高手指正。
  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 09:58 zuhd
楼上说的内存泄漏是存在的,泄漏了4* (4 + 4) = 32 BYTE,在后面的4次只是删除了成员指针,但没有删除自己(sizeof(B)),还有这种构造函数的嵌套是极不提倡的,如果基类的成员不是int,是int*的话,估计会让人很头痛的  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 13:23 alexandercer
事实上,是没有内存泄漏的,因为用了'~B(){delete pB;}',这样,针对堆上的内存会被依次析构并删除内存。 而且,就算没有delete pB; 泄漏也是可控的,因为是写在main里面的,系统会帮你回收这部分的内存的。

内存的事情,就是那样啦~~比较容易头痛的。。。  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 13:47 梦在天涯
仔细看了下,这样的结果就是正常的啊,疯了!  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 15:30 了修
哈哈 个人感觉这个东西比较有意思 自然也有高人觉着无聊
关于内存泄漏的事情没有追 没有机器哈
大家踊跃讨论啊  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 16:03 alexandercer
我又试了一下,写了点东东内嵌,输出调用过程,大家参考参考:

main [called by other code]
A::A(int) [called by other code]
B::B(int) test.cpp, 28
A::A(int) [called by other code]
B::B(int) test.cpp, 15
A::A(int) [called by other code]
B::B(int) test.cpp, 15
A::A(int) [called by other code]
B::B(int) test.cpp, 15
A::A(int) [called by other code]
B::B(int) test.cpp, 15
B::Display() test.cpp, 29
4
B::Display() test.cpp, 21
3
B::Display() test.cpp, 21
2
B::Display() test.cpp, 21
1
B::Display() test.cpp, 21
0
B::~B() [called by other code]
B::~B() test.cpp, 17
B::~B() test.cpp, 17
B::~B() test.cpp, 17
B::~B() test.cpp, 17


我不知道格式会不会出问题。。。。大家将就。。。  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 16:07 alexandercer
格式果然有问题,俺的缩进都没有了~~~~晕。。。。

  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-13 16:28 alexandercer
更加详细的调用stack:

A(int n) @ 7 @ test-noinsure.cpp
B(int n) @ 19 @ test-noinsure.cpp
A(int n) @ 7 @ test-noinsure.cpp
B(int n) @ 19 @ test-noinsure.cpp
A(int n) @ 7 @ test-noinsure.cpp
B(int n) @ 19 @ test-noinsure.cpp
A(int n) @ 7 @ test-noinsure.cpp
B(int n) @ 19 @ test-noinsure.cpp
A(int n) @ 7 @ test-noinsure.cpp
B(int n) @ 19 @ test-noinsure.cpp
B::Display() @ 27 @ test-noinsure.cpp
4
B::Display() @ 27 @ test-noinsure.cpp
3
B::Display() @ 27 @ test-noinsure.cpp
2
B::Display() @ 27 @ test-noinsure.cpp
1
B::Display() @ 27 @ test-noinsure.cpp
0
~B() @ 23 @ test-noinsure.cpp
~B() @ 23 @ test-noinsure.cpp
~B() @ 23 @ test-noinsure.cpp
~B() @ 23 @ test-noinsure.cpp
~B() @ 23 @ test-noinsure.cpp
~A() @ 9 @ test-noinsure.cpp
~A() @ 9 @ test-noinsure.cpp
~A() @ 9 @ test-noinsure.cpp
~A() @ 9 @ test-noinsure.cpp
~A() @ 9 @ test-noinsure.cpp


  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-18 11:45 witer666
那楼主是不是要Delete[] pB呢?  回复  更多评论
  
# re: 一道有意思的题目,大家看看输出:)  2009-01-22 18:11 Zero
一个简单的单向链表。
析构函数中delete操作,不断的调用下一个节点的析构函数和释放堆空间。
结论是没有内存泄漏。
  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理