class point
{
public:
point():x(0),y(0),z(0){}
point(int xx,int yy,int zz):x(xx),y(yy),z(zz){}
virtual ~point(){}
virtual int func(){return y+x+z;}
protected:
int x;
int y;
int z;
};point pt(10,20,30);
memset(&pt,0,sizeof(point));
int t=pt.func();//疑问:虚函数此时还能正常调用吗?printf("size:%d,t=%d",sizeof(point),t);//程序输出"size:16,t=0"今天在看别人的源码时发现类似这样的代码,以前好像在哪本书上看到过,说类实例中除了有成员变量之外还有编译器添加的虚函数表的指针.那么以上代码中memset不是会把pt中的"虚函数表指针"清除吗?如果会,pt.func();还能正常调用吗?
从输出结果和跟踪调试,发现程序一切正常.今天就是想求证一下,上面这样的代码到底有没有问题?是不是与特定的编译器有关?

解决方案 »

  1.   

    在构造函数里面memset会有问题C++对象模型中,凡是涉及虚技术的类,那么他的对象内存区块中就不单纯是用户定义这个类时看上去的那些数据结构,编译器会在当中安插一些数据或代码,用来实现响应的虚技术.于是当你用memset函数时会把这些编译器安插的东西冲掉, 程序执行结果变得未知. 这时候如果拷贝对象C++会使用memberwise拷贝, 此时编译器既拷贝用户定义的数据结构,还会对支持虚技术的相关设施进行适当的修改.
    如果对象没有用到虚技术, 那么就可以使用memset,因为这时该模型呈现出bitwize语意, 也就是说对应对象的这块内存就想看上去一样,背后没什么隐藏的东西, 可以逐位拷贝.
      

  2.   

    能调用是因为编译器已经把调用
    pt.func地址写好了。
    直接call。
      

  3.   

    memset(&pt,0,sizeof(point)); 跟位拷贝性质一样
    这样出错了,会把vtbl指针失效
      

  4.   

    memset应该只清0数据, 不会修改编译器加的东西,所以可以正常调用。
      

  5.   

    我们中国到现在都没有一个公司或高校做一个C++编译器,所以很多东西都理解不透。memset(&pt,0,sizeof(point));之后,程序没法子跳转,也不出错,我也困惑。
      

  6.   

    还是建议类的对象初始化不要使用memset
      

  7.   

    lz ,你的的问题, 让我想起另外一个问题来了。比如:
    A是基类, B是派生类B(const B& obj):A(obj){........};
    调用方式如下:B b1(xx);B b2=b1;   b1   肯定有虚函数表的维护,b2 也有,, 你说b1的数据拷到b2的时候,  b2的虚函数表有没有变动过????
    楼主,及楼上各位大牛,能帮忙解答一下嘛 谢谢了啊 
      

  8.   

    如果你把你的代码写成这样就知道原因了:
    point *pt = new point(10,20,30);
    memset(&pt,0,sizeof(point));
    int t=pt->func();//疑问:虚函数此时还能正常调用吗?printf("size:%d,t=%d",sizeof(point),t);//程序输出"size:16,t=0"你分别看这两种写法的反汇编就知道原因了,具体原因是这样的:
    首先,如果你用对象,因为你用对象,已经失去的多态的意义,也就是编译过后的程序中对于这样的代码:
    pt.func()因为它的地址不会变所以就直接用func函数所在的地址替换掉,也就是所谓的你更改的virtal table point的指针也是正常运行的,因为这里并不依靠pvtr.也就是说没有用到多态的地方是不会影响你的程序执行的,但是如果你更改成我给出的Code的话,你运行肯定会当掉,因为这里要依靠pvtr指针,而这时的指针已经为空了,所以当然会当掉,说到这里估计你已经知道原因了.
      

  9.   

    重新写一个C++编译器应该是没有意义,毕竟现在的优秀编译器还是很多的,GCC, OPEN64...
    尽管没有重新写但是更改还是很多,我们公司就修改了GCC, OPEN64等,所以重新写一个是没有意义的,更改才比较现实,毕竟这么优秀的工具不用自己要重新写当然就没有多大的意义了!