类对象与memset函数

来源:互联网 发布:算法导论中文第四版 编辑:程序博客网 时间:2024/05/19 16:21
memset某个结构或其它的数据类型在C语言中是非常常见,其目的是对结构或数据类型进行初始化,通常都是将变量置为0。在C++中,针对类对象除了用构造函数初始化对象外,也可以使用memset来进行初始化操作。当然这种情况极其少见,即使如此还是非常有必要谈一下这个问题。
下面是一个例子:

C++语言: Codee#12885
01 include <iostream>
02
03 class Base
04 {
05     int _n;
06 public:
07     Base (int n): _n(n) {}
08     virtual ~Base () {}
09     Base (const Base &rhs) { _n = rhs._n; }
10
11     void Show () { std::cout << "Base::Show()" << std::endl; }
12     virtual void Print () { std::cout << "Base::Print()" << std::endl; }
13 };
14
15 class Derive: public Base
16 {
17 public:
18     Derive (int i): Base(i) {}
19     ~Derive () {}
20     Derive (const Derive &rhs): Base(rhs) {}
21
22     void Print () { std::cout << "Derive::Print()" << std::endl; }
23 };
24
25 int main (void)
26 {
27     Derive *obj = new Derive(10);
28
29     std::cout << "Before delete ..." << std::endl;
30     obj->Show();
31     obj->Print();
32
33     std::cout << "After delete ..." << std::endl;
34     memset (obj, 0, sizeof(Derive));
35     obj->Show();
36     obj->Print();
37
38     return 0;
39 }

编译运行结果如下:


在使用memset初始化对象Obj之前,通过Obj调用Show和Print函数时程序运行正常,但是一旦利用Memset函数初始化该对象,再对该obj调用Show和Print函数,则程序立马崩溃。究其原因是因为初始化obj的时候,将obj包含的指向虚函数表VTBL的指针也清除了。包含虚函数的类对象都有一个指向虚函数表的指针,此指针被用于解决运行时和动态类型强制转换时虚函数的调用问题。该指针是被隐藏的,对程序员来说,这个指针也是不可存取的。当进行memset操作时,这个指针(即指向虚函数表的地址)的值也要被初始化,这样一来,只要一调用虚函数,程序便会崩溃。
这种现象在很多由C转向C++的程序员来说,很容易犯这个错误,而且这个错误很难查。
为了避免这种情况,记住对于有虚拟函数的类对象,决不能使用memset来进行初始化操作。而是要用缺省的构造函数或其它的init例程来初始化成员变量。
原创粉丝点击