悬浮指针,虚函数,逗号运算符等知识点综合题解决思路

悬浮指针,虚函数,逗号运算符等知识点综合题class A{public:~A(){coutA is deadendl}void virtual f

悬浮指针,虚函数,逗号运算符等知识点综合题
class A
{

public:
~A(){cout<<"A is dead"<<endl;}
void virtual f()
{
cout<<"A"<<endl;
}
};
class B
{

public:
~B(){cout<<"B is Dead"<<endl;}
void virtual f()
{
cout<<"B"<<endl;
}
};

int main()
{


A*pa=new A();//@1
pa->f();//@2
B* pb=(B*)pa;//@3
pb->f();//@4

delete pa,pb;//@5

B *pc=new B();//@6
pc->f();//@7

pa->f();//@8

return 0;
}

这道题纯粹是应试教育背景下诞生的题目,现实中谁写出这样的东东。。。哎。。批评结束,俺要问大家几个问题哈。。。
1.@5处只执行了delete pa(是不是因为逗号表达式的缘故?)
2.@8处输出B,说明pa指向的内存虽然被释放但内容没改变。(总觉得怪怪的,那块内存到底释放了没?)
3.关于虚指针,主要是@3处,强制转换后虚指针有甚么变化?
运行到@5时,单步调试(自己回去试下)
pb--------0x004319a0
|-[A]------{....}
|-__vfptr-----0x42601c

那个[A]是甚么东西??

还请高手们详解啊》》》》

[解决办法]
1.@5处只执行了delete pa(是不是因为逗号表达式的缘故?) 
----



2.@8处输出B,说明pa指向的内存虽然被释放但内容没改变。(总觉得怪怪的,那块内存到底释放了没?) 
-----
释放了


3.关于虚指针,主要是@3处,强制转换后虚指针有甚么变化?
---
虚函数的多态机制是根据VPtr指向VTable来确定的,此时pb指向的缓存里存储的是类A的VPtr,
所以调用的是类A版本的f()
[解决办法]
1.@5处只执行了delete pa(是不是因为逗号表达式的缘故?) 

应该是逗号表达式 ,delete pa作为一个表达式,pb作为一个表达式,所以执行了delete pa

2.@8处输出B,说明pa指向的内存虽然被释放但内容没改变。(总觉得怪怪的,那块内存到底释放了没?) 

对于一块释放了的内存,使用它是没有意义的,不要管它的值是什么,因为没有意义,所谓释放内存,就是将
内存的使用权归还系统,不代码将内存内容清空

3.关于虚指针,主要是@3处,强制转换后虚指针有甚么变化? 

强制转化后,B类的虚表函数指针指向了A类的虚表函数指针,出现这种情况是因为位拷贝造成的(一家之言)
显然,A,B类的结构是一样的,才出现了这种现象,比如在B类的f函数前加个virtual void test(void);
结果很明显
[解决办法]
1.@5处只执行了delete pa(是不是因为逗号表达式的缘故?) 

---------



因为逗号运算符的优先级比delete低,如果改成 

delete (pa,pb);//@5 

那么就只释放了 pb


2.@8处输出B,说明pa指向的内存虽然被释放但内容没改变。(总觉得怪怪的,那块内存到底释放了没?)


--------

释放了,但又声情回来了

delete pa,pb;//@5 // 把pa指向的空间释放了

B *pc=new B();//@6 // 给pc声情了空间,由于编译器内存管理的问题(vc),这个pc的空间刚好是前面释放的pa的空间
pc- >f();//@7 

pa- >f();//@8 // 所以pa的空间又有效了(和pc指向同一个空间)


你可以把B *pc=new B();去了,运行就回有问题




[解决办法]
1. 没错。
2. delete除了执行析构当作,把pa指向的内存标识为未占用,但是那块内存的内容暂时还没有改变,仍然包含原来的有效的可执行代码,所以@8还可以勉强执行。这种做法是不应该提倡的,如果该内存块由于多线程等原因被覆盖,马上会产生AV。
3. 类型转换时保留基类的virtual table。