zoukankan      html  css  js  c++  java
  • 【转】c++中使用memset初始化类对象

     https://blog.csdn.net/u010261063/article/details/70064090

     1 #include <iostream>
     2 #include <memory.h>
     3 using namespace std;
     4 
     5 class parent{
     6 public:
     7     virtual void output();
     8     virtual void output2();
     9 };
    10 
    11 void parent::output(){
    12     cout << "parent output" << endl;
    13 }
    14 
    15 void parent::output2(){
    16     cout << "parent output2" << endl;
    17 }
    18 
    19 class son : public parent{
    20 public:
    21     void output();
    22 };
    23 
    24 void son::output(){
    25     cout << "son" << endl;
    26 }
    27 
    28 int main(){
    29     son s;
    30     // memset(&s, 0, sizeof(s));  // 会段错误
    31     cout << "sizeof(s)=" << sizeof(s) << endl;  // 输出为8 没虚函数时1
    32     parent& p = s;
    33     p.output();
    34     return 0;
    35 }

    输出程序运行结果:程序不输出结果,运行出错!!分析一下原因:

    在使用memset初始化对象Obj之前,通过Obj调用output函数时程序运行正常,但是一旦利用Memset函数初始化该对象,再对该obj调用Show和Print函数,则程序立马崩溃。

    究其原因是因为初始化obj的时候,将obj包含的指向虚函数表VTBL的指针也清除了。包含虚函数的类对象都有一个指向虚函数表的指针,此指针被用于解决运行时和动态类型强制转换时虚函数的调用问题。

    该指针是被隐藏的,对程序员来说,这个指针也是不可存取的。当进行memset操作时,这个指针(即指向虚函数表的地址)的值也要被初始化,这样一来,只要一调用虚函数,程序便会崩溃。
    这种现象在很多由C转向C++的程序员来说,很容易犯这个错误,而且这个错误很难查。

    为了避免这种情况,记住对于有虚拟函数的类对象,决不能使用memset来进行初始化操作。而是要用缺省的构造函数或其它的init例程来初始化成员变量。

    当类中有虚函数的时候,编译器会为类插入一个我们看不见的数据并建立一个表。这个表就是虚函数表(vtbl),那个我们看不见的数据就是指向虚函数表的指针——虚表指针(vptr)。

    虚函数表就是为了保存类中的虚函数的地址。我们可以把虚函数表理解成一个数组,数组中的每个元素存放的就是类中虚函数的地址。

    当调用虚函数的时候,程序不是像普通函数那样直接跳到函数的代码处,而是先取出vptr即得到虚函数表的地址,根据这个来到虚函数表里,从这个表里取出该函数的地址,最后调用该函数。

    所以只要不同类的vptr不同,他对应的vtbl就不同,不同的vtbl装着对应类的虚函数地址,这样虚函数就可以完成它的任务了

  • 相关阅读:
    servlet中如何实现通过Spring实现对象的注入
    异步Socket
    JAVA NIO实现
    【Java并发】
    JAVA实现阻塞队列
    lock与synchronized比较
    线程执行顺序
    ConcurrentHashMap 1.8
    LeetCode 416 分割等和子集
    linux常用指令
  • 原文地址:https://www.cnblogs.com/qxxnxxFight/p/11131622.html
Copyright © 2011-2022 走看看